linux系统调用64位汇编与32位汇编不同及兼容

时间:2022-01-30 01:20:39

一、不同

1.系统调用号不同。比如x86中sys_write是4,sys_exit是1;而x86_64中sys_write是1, sys_exit是60。linux系统调用号实际上定义在/usr/include/asm/unistd_32.h和/usr/include/asm/unistd_64.h中。

2.系统调用所使用的寄存器不同,x86_64中使用与eax对应的rax传递系统调用号,但是 x86_64中分别使用rdi/rsi/rdx传递前三个参数,而不是x86中的ebx/ecx/edx。

3.系统调用使用“syscall”而不是“int 80”

例子:

32位:

global _start
_start:
jmp short ender
starter:
xor eax, eax ;clean up the registers
xor ebx, ebx
xor edx, edx
xor ecx, ecx

mov al, 4 ;syscall write
mov bl, 1 ;stdout is 1
pop ecx ;get the address of the string from the stack
mov dl, 5 ;length of the string
int 0x80

xor eax, eax
mov al, 1 ;exit the shellcode
xor ebx,ebx
int 0x80
ender:
call starter ;put the address of the string on the stack
db 'hello',0x0a
64位:
global _start           ; global entry point export for ld_start:    jump short string   ; get message addrcode:    ; sys_write(stdout, message, length)    pop     rsi         ; message address    mov     rax, 1      ; sys_write    mov     rdi, 1      ; stdout    mov     rdx, 13     ; message string length + 0x0a    syscall    ; sys_exit(return_code)    mov     rax, 60     ; sys_exit    mov     rdi, 0      ; return 0 (success)    syscallstring:    call    code    db 'Hello!',0x0a    ; message and newline
二、兼容

由于硬件指令的兼容,32位的程序在用户态不受任何影响的运行,由于内核保留了0x80号中断作为32位程序

的系统调用服务,因此32位程序可以安全触发0x80号中断使用系统调用,由于内核为0x80中断安排了另一

套全新的系统调用表,因此可以安全地转换数据类型成一致的64位类型,再加上应用级别提供了两套c库,

可以使64位和32位程序链接不同的库