写在前面
总结汇编语言第四五六章的内容, 包含汇编程序的编译链接, 多文件编译的方法, 以及汇编循环的一些内容.
约定的记号
()记号表示寄存器的内容
约定的一个记号, 表示一个寄存器或者一个内存单元中的内容, 例如:
(AX)
表示寄存器AX
寄存器中的数据,(20000H)
表示内存单元20000H
处的数据内容, 注意括号里面的内存单元地址用物理地址表示.((DS)*16+(BX))
表示(DS):(BX)
内存单元处的内容.
idata记号表示常量
immediate data 立即数
例如:
mov ax, [idata]
, 表示mov ax, [1]
,mov ax, [2]
等.mov ax, idata
, 表示mov ax, 1
,mov ax, 2
等.mov ds, idata
, 表示mov ds, 1
,mov ds, 2
等, 为非法指令.(不能直接向数据段寄存器传入, 而要通过 ax, bx 等寄存器传入)
第一个汇编程序
;; pseudo-instruction
;; associate `codeseg` with `cs` code segment
assume cs:codeseg
; pseudo-instruction, `codeseg` is the segment name
codeseg segment ; begin of `codseg` segment
;; asm instruction
mov ax, 0123H
mov bx, 0456H
add ax, bx
add ax, ax
;; function return
mov ax, 4c00H ;; interruption
int 21H
;;end of asm code
codeseg ends ; end of `codseg` segment
end
保存为a.asm
.
- 编译: 使用汇编器
masm
(我的GitHub里面上传了Learning_ASM/masm_etc.zip at main · Apocaly-pse/Learning_ASM (github.com)), 输入文件名, 一路回车即可, 最后会生成一个a.obj
目标文件. - 链接: 使用链接器
link
(同上), 输出文件名, 一路回车, 最后生成a.exe
文件.
汇编源程序中, 数据不能以字母开头, 需在开头补零或者在编译链接过程中使用分号终止, 快速编译链接.
.
使用debug查看程序运行情况
cs: 存源放文件长度(1.exe文件中机器码共有15字节)
DOS系统中可执行文件.EXE
的加载过程
- 找一段空闲内存区
SA:0000
- 该内存区的前256字节中创建一个
程序段前缀
(PSP), DOS利用这个数据区与被加载的程序进行通讯. - 从该内存区的156字节处开始(PSP后面), 将程序装入, 程序地址被设置为
SA+10H:0
, $(10){16}=(256){10}$. - 将该内存区的段地址存入
DS
中, 初始化其他相关寄存器, 然后设置指令寄存器(CS:IP
)指向程序入口.
一些汇编指令
inc, dec 自增自减
语法格式: inc ax
, 表示将寄存器AX中的内容加一后存回AX寄存器. (dec
为减一)
$\bigstar$loop
指令格式: loop 标号
. 执行步骤:
(cx)-=1
,- 判断
cx
中的值, 不为零则转至标号处执行程序, 否则继续向下执行.
cx
中的值会影响loop的执行结果, 所以通常用loop实现循环功能,用cx
中的数据指定循环次数.
一个例子: 计算$2^{10}$, 结果存在AX
中:
assume cs:code
code segment
mov ax, 2
mov cx, 9 ; 设置循环次数
s: add ax, ax ; 设定循环跳转位置
loop s ; 开始循环
mov ax,4c00h
int 21h
code ends
end
通过Debug执行, 可以得到结果(十六进制表示).
[BX]内存单元与寻址
与前面提到的[0]
类似, 不过数据段(基址为DS
寄存器内容)的偏移地址保存在BX
中, 例如:mov ax, [bx]
, 表示将DS:BX
中的数据存入AX
.