我想在汇编程序中做一个简单的程序,但我不明白为什么,我得到了一个错误。 我有一个运行Ubuntu 12.04的64位机器,和汇编编译器一样。 我的目标仅仅是在屏幕上打印string“你好”。
我写了这个:
#print.s .section .data .globl StringToPrint StringToPrint: .asciz "Hello" .globl _start _start: movq $4, %rax movq $1, %rbx movq $StringToPrint, %rcx movq $5, %rdx int $0x80 _done: ret
但是,这就是我得到的:
$ as print.s -o print.o $ ld print.o -o print $ ./print Hello[1] 10679 segmentation fault (core dumped) ./print
你为什么认为这发生? 任何想法?
这是修复:
#print.s .section .data .globl StringToPrint StringToPrint: .asciz "Hello" .globl _start _start: movl $5, %edx # string length movl $StringToPrint, %ecx # pointer to string to write movl $1, %ebx # file handle (stdout) movl $4, %eax # system call number (sys_write) int $0x80 # Passes control to interrupt vector #sys_exit (return_code) movl $1, %eax #System call number 1: exit() movl $0, %ebx #Exits with exit status 0 int $0x80 #Passes control to interrupt vector
正如迈克尔已经表示,你需要调用sys_exit
来避免分段错误。
编辑 :
这里很好的提到int 0x80
调用32位系统调用。
在x64系统上对系统调用使用int 0x80
用于向后兼容以允许运行32位应用程序。
在64位系统上使用syscall
指令是正确的。
这是一个工作版本:
.section .data StringToPrint: .asciz "Hello" .section .text .globl _start _start: movq $1, %rax # sys_write movq $1, %rdi # stdout movq $StringToPrint, %rsi # pointer to string to write movq $5, %rdx # string length syscall movq $60, %rax # sys_exit movq $0, %rdi # exit code syscall
在Linux和其他操作系统中,调用约定与32位和64位应用程序不同。 另外,对于Linux系统调用号码也是不同的。 这就是你在Linux amd64中调用write
系统调用的方法:
; sys_write(stdout, message, length) mov rax, 1 ; sys_write mov rdi, 1 ; stdout mov rsi, message ; message address mov rdx, length ; message string length syscall
此外,您的应用程序需要调用sys_exit
来终止,而不是使用ret
返回。 阅读您平台的调用约定。