我想在汇编程序中创建一个简单的程序,但我不明白为什么,我得到了一个错误。 我有一台运行Ubuntu 12.04的64位机器,以及作为汇编编译器的“as”。 我的目标只是在屏幕上打印字符串“Hello”。
我写了这个:
#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
为什么你认为这会发生?有什么想法吗?
答案 0 :(得分:2)
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
返回。阅读适用于您平台的调用约定。
答案 1 :(得分:1)
以下是修复:
#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
正如Michael已经说过你需要调用sys_exit
以避免分段错误。
编辑:
值得一提的是int 0x80
调用了32位系统调用
在x64系统上使用int 0x80
用于syscall用于向后兼容,以允许运行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