所以我正在学习使用NASM的x86程序集,我正在尝试创建一个打印出整数的简单函数。我的代码......
print_integer: ; Integer input stored in eax
mov ecx, 10
print_integer_loop:
mov edx, 0
div ecx ; eax /= 10 | edx = eax % 10
or edx, 0x30 ; Convert 0-9 to ‘0’-‘9’
push edx ; Push remaineder to stack
mov eax, 4 ; sys_write
mov ebx, 1 ; STDOUT
mov ecx, esp ; Top of Stack to ecx
mov edx, 1 ; Print 1 byte
int 0x80 ; syscall
pop edx
cmp eax, 0 ; Compare quotient to 0
jnz print_integer_loop
_main:
mov eax, 4251
call print_integer
mov eax, 1 ; ‘Exit’ System call
mov ebx, 0 ; Exit with error code 0
int 0x80 ; syscall
当我运行此代码时,没有任何反应。它只是结束而不打印任何东西。我查看过所有相似的主题,但我发现没有任何帮助。我不确定会出现什么问题,所以任何见解都会很棒。
编辑:我将NASM更新为更新的版本,因此我可以使用x86_64系统调用。代码如下print_integer: ; Assume integers is in r15
push 0x0a ; Push endline character
mov r14, 1 ; Setup counter for printing
stack_loop:
mov rax, r15 ; Move r15 to rax for divison
xor rdx, rdx ; Avoids error
mov rcx, 10
div rcx ; rax = rdx:rax / rcx | rdx = rdx:rax % rcx
add rdx, '0' ; Convert 0-9 to ‘0’-‘9’
push rdx ; Push remainder to stack
mov r15, rax ; Move quotient to r15 register
inc r14 ; Counter + 1
cmp r15, 0 ; Compare quotient to 0
jne stack_loop ; If not zero, loop
; Characters are now on stack in reverse order
print_loop:
mov rsi, rsp ; Put remainder in rsi
mov rdx, 1 ; Print 1 char (length)
mov rax, 0x2000004 ; System call write
mov rdi, 1 ; Standard output, number of bytes
syscall ; Invoke kernal
dec r14 ; Counter - 1
pop r15 ; Remove off top of stack
cmp r14, 0
jne print_loop
ret
希望这可以帮助将来的某个人。这可能不是最好的方法,但这是一种方式。
答案 0 :(得分:1)
首先,您首先输出第一个余数。您用来写十进制数的方法将以相反的顺序输出数字:数字4251将打印为“1524”。
然后你的程序包含一些错误:
程序现在如何应该无休止地输出数字“1”。我在我的电脑上进行了测试,确实如此!
固定程序如下所示:
print_integer:
mov ecx, 10
; print_integer_loop is no longer needed
mov edx, 0
div ecx
or edx, 0x30
push eax ; inserted
push edx
mov eax, 4
mov ebx, 1
mov ecx, esp
mov edx, 1
int 0x80
pop edx
pop eax ; inserted
cmp eax, 0
jnz print_integer ; changed
ret ; inserted
main:
mov eax, 4251
call print_integer
mov eax, 1
mov ebx, 0
int 0x80
我在Ubuntu 12上测试了该程序并且运行良好(但是它将数字4251打印为“1524”)。
顺便说一下:为什么要将主要功能命名为“_main”?
您是否指示链接器链接到“_main”作为入口点(如果是:为什么不“_start”)或者您是否使用 Windows 的正常启动代码?
如果最后一个是这种情况:程序中的“int 0x80”系统调用只能在Linux下运行;在Windows下运行代码或将代码与Windows代码混合并在Linux下运行结果将无效!
---编辑---
因为我没想到你使用Mac我没有提到Mac OS X:
由于Windows不使用“int 80h”,包含此指令的程序可能会在Windows下崩溃。
我知道Mac OS X也使用“int 80h”,因此该指令不会导致程序崩溃。我也知道在Mac OS X下,“int 80h”的使用与Linux完全不同。据我所知,参数在Mac OS X下在堆栈上传递。
编写程序的方式绝对只能在Linux下运行,而不是在Mac OS X下运行!
不幸的是,我对Mac OS X了解不多,所以我不能再给你提供任何暗示。