这需要在纯汇编中完成(即没有库或对C的调用)。
我理解问题的本质:需要将整数除以10,将一位数的余数转换为ASCII,然后输出,然后用商重复该过程。
但由于某种原因,它只是不起作用。我在x86上使用NASM。
这是我现在所拥有的(不输出任何内容,但也不会抛出任何汇编错误):
; integer to output is stored in eax
mov ecx, 10 ; for base 10
loop:
div ecx ;EAX contains the quotient, EDX the remainder
; Do something to EDX to convert it to ASCII, not sure if this is correct
add edx, '0'
push eax ;We'll be playing with EAX to output EDX, save EAX to the stack
mov eax, 4 ; sys_write
mov ebx, 1 ; to STDOUT
mov ecx, edx
mov edx, 1
int 0x80
pop eax ;restore EAX
cmp eax, 0 ;If EAX is 0, our job is done
jnz loop
有许多问题与此类似(即this和this),但我在实施中迷失了方向。 This question(对于DOS)也有帮助,但我仍然感到困惑。
我必须在这里遗漏一些东西。想法?
答案 0 :(得分:5)
至少还有两个问题。除了@sarnold提到的ecx
的腐败之外:
div ecx
将64位值edx:eax
除以ecx
,因此您需要确保在分割前将edx
设置为0。
write
系统调用的第二个参数(在ecx
中)应该是指向包含要打印的字符的缓冲区的指针,而不是字符本身。
解决第二个问题的一种方法是将包含要打印的字符的寄存器推送到堆栈,然后将堆栈指针esp
分配给ecx
(堆栈指针指向最近推送的项目,x86存储值little-endian,所以第一个字节是低8位)。 e.g。
push edx ; save value on stack
mov eax, 4 ; sys_write
mov ebx, 1 ; to STDOUT
mov ecx, esp ; first byte on stack
mov edx, 1 ; length = one byte
int 0x80
pop edx ; remove what we pushed (or "add esp, 4" would do just as well here;
; we don't need the actual value again)
这应该足以获得一些输出......
(但在那时,您可能会注意到算法的特征"并且想要重新考虑如何存储分部产生的数字!)
答案 1 :(得分:2)
您在日常工作的顶部正确设置ecx
至10
,但稍后覆盖ecx
:
mov eax, 4 ; sys_write
mov ebx, 1 ; to STDOUT
mov ecx, edx ;;; oops -- lost the 10
mov edx, 1
int 0x80
尝试将loop
向上移动一行,以便每次循环时ecx
重新初始化为10
。