从单词数组

时间:2017-12-04 13:50:53

标签: arrays assembly byte x86-16 emu8086

所以,从一个单词数组开始,我必须创建一个数组来包含每个给定单词的数字,用基数10写成。
所以,如果我有

s DW 12345, 20778, 4596 

结果应该是这个BYTE数组

t DB 1, 2, 3, 4, 5, 2, 0, 7, 7, 8, 4, 5, 9, 6

我被建议怎么做,我已经尝试过实现它,但我收到以下错误

  

对操作或指令的争论具有非法规模“

(关于“推al”和“pop al”行)

以下是我尝试实施的代码:

ASSUME cs:text_,ds:data_

data_ SEGMENT

s dw 12345, 20778, 4596
l equ $-sir 
d db (l/2)*5 dup (?)

data_ ENDS

text_ SEGMENT
start:
    mov ax, data_
    mov ds, ax
    mov es, ax
    mov si, offset s 
    mov di, offset d
    mov cx, l    ;storing the length of s
    mov dl, 10   
    mov ax, [si] ;storing the data of si into ax so that the division can be made
    cld          ;setting the direction flag
    jmp loop1    
    cloop1:
        div dl   ;divide by 10 so we can get the remainder
        push al  ;ERROR LINE ;my plan was to store the value of al into the stack, so I can store the remainder into al
        mov al, ah
        stosb    ;we add the remainder to the final line
        pop al   ;ERROR LINE ;my plan was to get the value of al from the stack and do the instruction once againq
    loop cloop1
    loop1:        ;the role of this loop is to repeat the instruction as long as there are words left (similar to while instruction in C++)
        cmp ax, 0  
        jg cloop1  ;if there are words left, the code keeps on being executed 
    loop loop1
    mov ax, 4c00h
    int 21h
    text_ ENDS
    end start   

这是基于它的想法(用C ++表示):

nr=0;
while(x>0)
 {c=x%10;
  nr=nr+x*10;
  x=x/10;
 }
cout<<nr;

提前致谢并对任何错误表示歉意。关于我的问题的任何建议将不胜感激

2 个答案:

答案 0 :(得分:1)

您不能将8位寄存器压入堆栈。在16位模式下,您只能推送和弹出16或32位寄存器。尝试将push alpop al替换为push axpop ax

答案 1 :(得分:1)

你的C循环是理智的,除了nr=nr+x*10;我认为你转换回一个反转的十进制数字整数?这并不是一个在asm中考虑它的有用方法,因为你没有cout << nr库功能。

通常的策略(特别是如果你只需要打印成一个字符串)是从一个指向缓冲区的 end 的指针开始并向前工作。 (例如dec di / ... / div / add dl, '0' / mov [di], dl / test ax,ax / jnz)。有关x86-64版本,请参阅示例How do I print an integer in Assembly Level Programming without printf from the c library?。将数字转换循环移植到具有16位整数的x86-16是很简单的;我没有使用任何x86-64特定的东西。

一旦你的商变为0,你就退出循环;你完成了,你的印刷顺序是你的数字。数字来自当前指针(di)到缓冲区末尾的任何位置。将其提供给打印字符串函数(我认为int 21h具有其中之一)。

如果要将结果放在具有固定起始位置的数组中,则可以复制。但是如果你只需要在连续缓冲区中将所有数字作为整数,那么你就可以得到它。从为缓冲区分配的空间末尾的最后一个单词开始。当您获得单词中的所有数字时,请转到下一个单词(sub si,2),但不要移动di,因此下一个单词的数字是存储在高位地址字的数字之前。或者,如果您要针对代码大小进行优化,请使用lodswstosb

当您完成源数组的最后一个单词时,di指向数组数组的开头。

Push在循环中生成然后pop是处理div / mod算法生成最低有效第一顺序数字的另一种方法。但它需要一个单独的循环来弹出。正如@Fuz指出的那样,你必须推/弹整个16位寄存器。