x86 64架构汇编语言

2、x86汇编框架

1、课程目标

  • 掌握x86汇编程序的基本结构
  • 理解数据段和代码段
  • 掌握基础汇编指令
  • 能够编写简单的汇编程序

2、名词解释

术语 说明
.data 已初始化数据段
.data? 未初始化数据段
.const 常量数据段
.code 代码段
PROC/ENDP 过程定义
INVOKE 高级函数调用
立即数 直接写在指令中的数值
操作数 指令的数据来源/目标

3、代码实现

1. MASM基础框架

; hello.asm - MASM x86基础框架
.386                    ; 使用386指令集
.model flat, stdcall    ; 平坦内存模型, stdcall调用约定
option casemap:none     ; 区分大小写

; 引入Windows API
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib

; 数据段
.data
    szTitle     db "Hello", 0
    szMessage   db "Hello, Assembly!", 0

; 未初始化数据段
.data?
    hInstance   dd ?

; 代码段
.code
start:
    ; 调用MessageBox
    invoke MessageBoxA, NULL, addr szMessage, addr szTitle, MB_OK
    
    ; 退出
    invoke ExitProcess, 0
end start

2. 基础数据移动指令

.code
DataMove PROC
    ; MOV - 移动数据
    mov eax, 100        ; 立即数 -> 寄存器
    mov ebx, eax        ; 寄存器 -> 寄存器
    mov ecx, [ebx]      ; 内存 -> 寄存器
    mov [edx], eax      ; 寄存器 -> 内存
    ; mov [eax], [ebx]  ; 错误! 不能内存到内存
    
    ; XCHG - 交换
    mov eax, 1
    mov ebx, 2
    xchg eax, ebx       ; eax=2, ebx=1
    
    ; LEA - 加载有效地址
    lea eax, [ebx + ecx*4 + 100]  ; 计算地址,不访问内存
    
    ; PUSH/POP - 栈操作
    push eax            ; ESP-=4, [ESP]=EAX
    pop ebx             ; EBX=[ESP], ESP+=4
    
    ret
DataMove ENDP

3. 完整示例:简单加法

.386
.model flat, stdcall
option casemap:none

include kernel32.inc
includelib kernel32.lib
include msvcrt.inc
includelib msvcrt.lib

.data
    num1    dd 10
    num2    dd 20
    result  dd ?
    fmt     db "Result: %d", 10, 0

.code
start:
    ; 加载第一个数
    mov eax, [num1]
    
    ; 加上第二个数
    add eax, [num2]
    
    ; 保存结果
    mov [result], eax
    
    ; 打印结果
    invoke crt_printf, addr fmt, [result]
    
    ; 退出
    invoke ExitProcess, 0
end start

4. 内联汇编在C中使用

#include <stdio.h>

int Add(int a, int b) {
    int result;
    __asm {
        mov eax, a
        add eax, b
        mov result, eax
    }
    return result;
}

int main() {
    printf("=== 内联汇编 ===\n\n");
    
    int sum = Add(10, 20);
    printf("10 + 20 = %d\n", sum);
    
    // 直接内联
    int x = 5, y = 3, diff;
    __asm {
        mov eax, x
        sub eax, y
        mov diff, eax
    }
    printf("5 - 3 = %d\n", diff);
    
    return 0;
}

5、课后作业

5.1、作业1:编写Hello World

编写一个纯汇编的Hello World程序。

5.2、作业2:实现乘法

用汇编实现两个整数相乘并打印结果。