【发布时间】:2022-01-01 08:33:23
【问题描述】:
所以我在 Stack Overflow 上找到了很多答案,但我仍然无法让它工作。我的代码有什么问题?
mov al, 12
mov bl, 12
mul bl ; answer in ax
aam
mov bx, 10 ; Divisor constant
xor cx, cx ; Clear counter
.a: xor dx, dx ; Clear dx
div bx ; Divide ax with bx, quotient in al, remainder in ah
mov dh, ah ; Move ah to dh, so we can push the 16 bit register of dx
push dx ; Push dx which contains the remainder
inc cx ; Increment counter
test al, al ; If al (the quotient) is not zero, loop again.
jnz .a
.b: pop dx ; Pop the last remainder to dx from stack
add dx, '0' ; Add '0' to make it into character
push cx ; Push loop counter to stack so printing wont interfere with it
mov eax, 4 ;
mov ebx, 1 ;
mov ecx, edx ; Print last popped character
mov edx, 1 ;
int 0x80 ;
pop cx ; Pop the loop counter back to cx
loop .b ; loop for as long as cx is not 0
【问题讨论】:
-
删除
aam。请注意,div bx(16 位除数)将余数留在dx商在ax中。即使剩余部分在ah中,您也应该将其移至dl而不是dh。照原样删除mov dh, ah并将test al, al更改为test ax, ax。此外,我相信 int 80h 服务 4 在ecx中采用 pointer,而不是代码点。因此将pop dx移动到pop cx之后,并将mov ecx, edx替换为lea ecx, [esp + 2](因此它将指向仍在堆栈内存中的dx值)。 -
@ecm 你对其他东西是对的,但
lea ecx, [esp + 2]是不对的,因为它将一堆未知字符和一个段错误转储到终端。 -
它可以与
mov ecx, edx一起使用吗? -
我忘记了
add dx。将它从它所在的位置移到push dx之前。此外,您还需要在loop前面添加地址大小前缀,以便它使用 16 位的 a16 地址大小,而不是您部分的默认 a32。那么你的.b循环应该是.b:\push cx\mov eax, 4\mov ebx, 1\lea ecx, [esp + 2]\mov edx, 1\int 80h\pop cx\pop dx\@987654353pop dx\@98765435353 -
对每个字符进行单独的
write系统调用是非常低效的。相反,存储到堆栈上的缓冲区(按降序)并进行一次write调用,如How do I print an integer in Assembly Level Programming without printf from the c library? 所示