x86 64架构汇编语言
5、保护模式下的寻址方式
1、课程目标
- 理解实模式与保护模式的区别
- 掌握各种内存寻址方式
- 理解段寄存器的作用
- 掌握有效地址计算
2、名词解释
| 术语 | 说明 |
|---|---|
| 实模式 | 16位地址模式(1MB) |
| 保护模式 | 32/64位模式,内存保护 |
| 平坦模式 | 段基址为0的保护模式 |
| 有效地址 | 指令中计算出的地址 |
| 基址寄存器 | 地址计算的基础 |
| 变址寄存器 | 乘以比例因子的寄存器 |
| 比例因子 | 1, 2, 4, 8 |
3、代码实现
1. 寻址方式
.code
Addressing PROC
; 立即寻址
mov eax, 12345678h ; 立即数
; 寄存器寻址
mov eax, ebx ; 寄存器到寄存器
; 直接寻址
mov eax, [00401000h] ; 直接地址
; 寄存器间接寻址
mov eax, [ebx] ; [EBX]
; 基址+偏移寻址
mov eax, [ebx + 100] ; [EBX + disp]
; 变址寻址 (带比例因子)
mov eax, [ecx*4] ; [index * scale]
; 基址+变址
mov eax, [ebx + ecx*4] ; [base + index * scale]
; 基址+变址+偏移 (最复杂形式)
mov eax, [ebx + ecx*4 + 100]
ret
Addressing ENDP
2. 有效地址计算
.data
array dd 10, 20, 30, 40, 50
.code
ArrayAccess PROC
; 访问数组元素
lea ebx, array ; EBX = 数组基址
mov ecx, 2 ; 索引 = 2
; 计算 array[2] 的地址
; 地址 = base + index * sizeof(element)
mov eax, [ebx + ecx*4] ; EAX = array[2] = 30
; 使用LEA计算地址
lea edx, [ebx + ecx*4] ; EDX = &array[2]
ret
ArrayAccess ENDP
3. 结构体访问
#include <stdio.h>
typedef struct {
int id; // +0
char name[32]; // +4
int age; // +36
} Person;
int main() {
printf("=== 结构体寻址 ===\n\n");
Person p = {1, "Alice", 25};
int age;
// 通过偏移访问成员
__asm {
lea ebx, p // EBX = &p
mov eax, [ebx + 36] // 访问 age (偏移36)
mov age, eax
}
printf("年龄: %d\n", age);
printf("偏移量: id=%d, name=%d, age=%d\n",
offsetof(Person, id),
offsetof(Person, name),
offsetof(Person, age));
return 0;
}
4、课后作业
4.1、作业1:数组遍历
用汇编实现数组求和。
4.2、作业2:结构体操作
定义一个结构体并用汇编访问其成员。