Day4:Linux汇编框架、操作系统与汇编器、主函数跳转流程

Linux汇编框架、操作系统与汇编器、主函数跳转流程

Linux(NASM)汇编框架

  • Linux和Windows的不同主要有:

    • 系统调用方式不同:

      • Windows提供API,可以直接利用系统函数

      • Linux需要用系统调用号触发系统调用。系统调用号存入特定寄存器后使用触发指令,触发系统调用

        触发指令:

        ​ 32位(x86):int 0x80

        ​ 64位(x64):syscall

        参数传递:

        ​ 32位:eax(系统调用号),ebx、ecx、edx、esi、edi、ebp(参数)。

        ​ 64位:rax(系统调用号),rdi、rsi、rdx、r10、r8、r9(参数)。

        32位下exit示例:

        1
        2
        mov eax,1		;32位下,exit的系统调用号为1
        int 0x80 ;系统调用号存入寄存器后,触发系统调用
    • 可执行文件格式不同:

      • Windows使用PE文件格式
      • Linux使用ELF文件格式
    • 其他细节:

      • Linux在段名前必须添加section,只有.text段没有.code段(实际上由汇编器决定,详见下一部分)
      • Linux使用0xA作为字符串结束符
  • 32位汇编框架

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    section .data
    msg db "HelloWorld",0xA
    len equ $ - msg ;用变量len记录msg的长度($表示当前变量的地址,减去msg的地址就是msg的长度)

    section .text
    global _start
    _start:
    mov eax,4 ;eax存放系统调用号4:sys_write
    mov ebx,1 ;参数1:文件描述符,1表示标准输出stdout
    mov ecx,msg ;参数2:要打印的数据地址
    mov edx,len ;参数3:打印的字节数
    int 0x80

    mov eax,1 ;eax存放系统调用号1:sys_exit
    mov ebx,0 ;参数1:退出状态码(0表示成功)
    int 0x80
  • 64位汇编框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
section .data
msg db "HelloWorld",0xA
len equ $ - msg

section .text
global _start
_start:
mov rax,1 ;rax存放系统调用号1:sys_write
mov rdi,1 ;参数1:文件描述符,1表示标准输出stdout
mov rsi,msg ;参数2:要打印的数据地址
mov rdx,len ;参数3:打印的字节数
syscall

mov rax,60 ;rax存放系统调用号60:sys_exit
xor rdi,rdi ;参数1:退出状态码(0表示成功)
syscall

操作系统与汇编器

  • Windows:主要有MASM和NASM两种汇编器
    • MASM(Microsoft Macro Assembler),主要集成在visual studio中
      • 段名前不要求加section,可以直接用 .段名 声明
      • 指令存放在.code段
      • .code段,函数以 func_name proc 开始,以 func_name endp 结束
      • 使用Intel风格,即 指令 目标操作数,源操作数
    • NASM(Netwide Assembler),跨平台汇编器,支持Windows、Linux、macOS
      • 段名前要求加section,用 sectino .段名 声明
      • 指令存放在.text段
      • .text段,函数用 global func_name 声明后再定义
      • 使用Intel风格
  • Linux:主要有NASM和GAS两种汇编器
    • NASM同上
    • GAS(GNU Assembler),Linux默认汇编器
      • 段名前要求加.section,用 .section .段名 声明
      • 指令存放在.text段
      • .text段,函数用 .global func_name 声明后再定义
      • 使用AT&T风格,即 指令 源操作数,目标操作数

主函数跳转流程

  • 环境:vs2022,Debug x86/x64,Release x86/x64

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    ;x86 debug 跳转特征
    ;step1
    jmp ;直接jmp

    ;step2
    call ;第一个call

    ;step3
    call
    call <-- ;连续两个call,进第二个

    ;step4
    2*jz-->call
    mov
    call ;两个jz指向的同一个call且此call后紧跟mov和call

    ;step5
    mov
    push
    mov
    push
    mov
    push
    call ;连续push3个参数入栈后的call

    ;step6
    jmp
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ;x86 Release 跳转特征
    ;step1
    call
    jmp ;call后的jmp

    ;step2
    push
    push
    push
    call ;连续push3个参数入栈后的call
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    ;x64 Debug 跳转特征 
    ;step1
    jmp ;直接jmp

    ;step2
    call ;第一个call

    ;step3
    call
    call <-- ;连续两个call进第二个

    ;step4
    2*jz-->call
    mov
    call ;两个jz指向的同一个call且此call后紧跟mov和call

    ;step5
    mov
    mov
    mov
    mov
    mov
    call ;连续5个mov后的call(传参)

    ;step6
    jmp ;直接jmp
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ;x64 Release 跳转特征 
    ;step1
    call
    jmp ;call后的jmp

    ;step2
    mov
    mov
    mov
    call
    mov
    call ;三个mov后的call(传参)且此call后紧跟mov和call

Day4:Linux汇编框架、操作系统与汇编器、主函数跳转流程

https://sydzi.github.io/2025/07/11/Day4-Linux汇编框架/

作者

SydzI

发布于

2025-07-11

更新于

2025-10-03

许可协议

评论