汇编语言
实方式执行环境
-
寄存器
-
32位寄存器EAX、EBX、ECX、EDX、ESP、EBP、ESI和EDI
16位寄存器AX、BX、CX、DX、SP、BP、SI和DI
8位寄存器AH、AL、BH、BL、CH、CL、DH和DL
-
段寄存器CS、DS、SS和ES,以及段寄存器FS和GS。寄存器CS含有当前代码段的段值,寄存器DS含有当前数据段的段值,寄存器SS含有当前堆栈段的段值。
-
实方式下指令指针寄存器EIP中的高16位必须是0,相当于只有低16位的IP起作用。
-
实方式下堆栈指针寄存器ESP中的高16位必须是0,相当于只有低16位的SP起作用。
-
-
指令集
存储器分段管理
-
存储器分段条件
-
实方式下可访问的物理地址空间只有1M:
00000H -- FFFFFH
-
实方式下每个逻辑段必须满足如下两个条件:
- 第一,逻辑段的起始地址必须是16的倍数
- 第二,逻辑段的最大长度为64K
-
存储段,既可以相连,也可以重叠
-
-
物理地址计算
-
段起始地址有如下形式:
bbbbbbbbbbbbbbbb0000
-
20位段起始地址的高16位XXXX称为
段值
-
段起始地址与段值的关系:
段起始地址 = 段值×16
-
物理地址、段值和偏移之间关系:
物理地址 = 段值×16 + 偏移
例如:
逻辑地址 对应物理地址 1234:3456 15796 1234:34A8 157E8 FFF0:0000 FFF00
-
由于段可以重叠,一个物理地址可对应多个逻辑地址
-
-
段寄存器引用
-
实方式下,段寄存器中的内容是段值。
-
代码段寄存器CS给出当前代码段的段值,堆栈段寄存器SS给出当前堆栈段的段值,数据段寄存器DS给出当前**缺省数据段的段值**。附加段寄存器ES、FS、GS也可以给出其他数据段的段值。
-
每当需要产生一个20位的物理地址时,CPU会自动引用一个段寄存器获得段值,形成20位的段起始地址,再加上有效地址(偏移)。
示例一:
MOV AX,0F000H MOV DS,AX ;DS含段值F000H MOV ESI,0 ;使ESI为0(最低地址偏移为0) MOV EAX,[ESI] ;取出最低的4个字节 //起始地址默认为DS MOV EDX,[ESI+4] ;再取出次低的4个字节
示例二:
MOV AX, 0F000H ;对应源段的段值 MOV DS, AX ;使DS含源数据段的段值 MOV AX, 0B800H ;对应目标段的段值 MOV ES, AX ;使ES含目标数据段的段值 MOV ESI, 0 ;ESI=0 MOV EDI, 2000H ;EDI=2000H MOV ECX, 8 ;ECX=8,作为循环计数 NEXT: MOV EAX, [ESI] ;自动引用DS,偏移为ESI值 @here MOV [ES:EDI], EAX ;引用段寄存器ES,偏移为EDI值 @here ADD ESI, 4 ADD EDI, 4 LOOP NEXT
-
-
16位存储器寻址方式
-
16位的存储器寻址方式,主要应用于实方式。在实方式下,存储段的长度不超过64K,存储单元的有效地址是16位。
-
16位有效地址EA可以有多种表示形式
-
基址部分可以是寄存器BX或BP;
变址部分可以是寄存器SI或DI;
位移量采用补码形式表示,在计算有效地址时,如位移量是8位,则被带符号扩展成16位。
演示16位存储器寻址方式的使用:
略去操作数为8位/16位。
给出操作数是32位:
```asm
MOV EAX, [SI]
ADD EDX, [DI-4]
SUB [BX+DI], ECX
MOV [BX+SI+3], EAX
```
以下使用方式非法:
```asm
MOV EAX, [SI+DI]
MOV DX, [AX]
MOV [CX-3], AL
```
针对16位存储器寻址方式的取有效地址指令:
```asm
MOV DI, 1234H ;DI=1234H
MOV BX, 16H ;BX=0016H
LEA SI, [DI+BX+5] ;SI=124FH
LEA EAX, [BX+DI-2] ;EAX=00001248H
```
汇编语言源程序
-
系统功能调用
系统功能类似于子程序。可以认为系统功能是由操作系统提供的子程序。
-
单个段的源程序
segment text ;命名段text org 100H ;段内偏移从100H开始计算 ; ;代码内容 MOV AH, 4CH INT 21H ;返回操作系统 ; hello db "Hello world!", 0DH, 0AH, '$' ;一些数据
演示程序dp61.asm
segment text ;命名段text org 100H ;段内偏移从100H开始计算 ; MOV AX, CS MOV DS, AX ;使数据段与代码段相同 MOV DX, hello ;DX=hello的段内偏移 MOV AH, 9 INT 21H ;显示hello开始的字符串(以$结尾) ; MOV AH, 4CH INT 21H ;返回操作系统 ; hello db "Hello world!", 0DH, 0AH, '$'
-
多个段的源程序
整体框架
segment code ;定义段code .start: ;启动标号 MOV AX, stack MOV SS, AX ;设置堆栈段寄存器 MOV SP, stacktop ;设置堆栈顶 ; MOV AX, data MOV DS, AX ;设置数据段寄存器 ; 代码部分省略 MOV AH, 4CH INT 21H ; ;内部子程序 ToASCII: ;子程序入口 AND AL, 0FH ADD AL, '0' CMP AL, '9' JBE LAB3 ADD AL, 7 LAB3: RET ;---------------------------------------------------------- segment data ;定义段data prompt db "Press a key: ",'$' newline db 0DH,0AH,'$' result db 0,0 ;存放十六进制数ASCII码 db 'H',0DH,0AH,'$' ;结果字符串后半部分 ; 0ah和0dh组合起来是换行,$是字符串的结束标记 ;---------------------------------------------------------- segment