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

一、不同

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 addr
code:
    ; 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)
    syscall

string:
    call    code
    db 'Hello!',0x0a    ; message and newline
二、兼容

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

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

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

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


你可能感兴趣的:(linux系统调用64位汇编与32位汇编不同及兼容)