第五章的代码很多地方是手动写死的,本章就是要利用新的汇编知识改写第五章的代码,变的更加灵活和简洁。
图 6-1 以两个逻辑段的视角看待同一个内存区域
movsb、movsw指令
这两个指令通常用于把数据从内存中的一个地方批量地传送(复制)到另一个地方,movsb 的传送是以字节为单位的,而 movsw 的传送是以字为单位的。
movsb 和 movsw 指令执行时,原始数据串的段地址由 DS 指定,偏移地址由 SI(Source Index) 指定,简写为DS:SI;要传送到的目的地址由 ES:DI(Destination Index) 指定;传送的字节数(movsb)或者字数(movsw)由 CX 指定。除此之外,还要指定是正向传送(低地址端到高地址端)还是反向传送(高地址端到低地址端)。正向传送时,每传送一个字节(movsb)或者一个字(movsw),SI 和 DI 加 1 或者加 2;反向传送时,每传送一个字节(movsb)或者一个字(movsw)时,SI 和 DI 减去 1 或者减去 2。不管是正向传送还是反向传送,也不管每次传送的是字节还是字,每传送一次,CX 的内容自动减一。
标志寄存器 FLAGS的第 10 位是方向标志 DF(Direction Flag),通过将这一位清零(cld指令)或者置 1(std指令),指示传送方向正向或反向。
单纯的 movsw 只能执行一次,如果希望处理器自动地反复执行,需要加上指令前缀 rep(repeat),意思是 CX 不为零则重复。rep movsw的操作码是0xF3 0xA5,它将重复执行 movsw 直到 CX 的内容为零。
标志寄存器 FLAGS
loop指令
loop 标号 ;编译后对应的机器码表明,操作码后跟的是相对于标号的偏移量,即
;标号地址-loop指令地址-loop指令的长度。其实当前地址是loop指令地址
;减去loop指令的长度。这一点和`jmp near 标号`指令类似。
CPU执行loop指令之前,执行(cx)=(cx)-1,再判断cx中的值,不为0则转到标号处执行程序(当前IP的值加偏移量),否则向下执行。
编程实现
学习下本章新的知识点之后,可以参考作者书上附带源码,进行手动编程如下。
;文件名:c06_01_mbr.asm
;文件说明:硬盘主引导扇区代码
;参考书:《x86汇编语言:从实模式到保护模式》李忠 著
;代码功能:得到标号number对应偏移地址的十进制各数位,显示到屏幕
jmp near start ;跳过数据区
text:
db 'L',0x07,'a',0x07,'b',0x07,'e',0x07,'l',0x07,' ',0x07,'o',0x07,\
'f',0x07,'f',0x07,'s',0x07,'e',0x07,'t',0x07,':',0x07
number:
db 0,0,0,0,0
start:
;把"Label offset:"字符串从0x07c0:text传送到0xb800:0000
mov ax,0x07c0
mov ds,ax
mov si,text
mov ax,0xb800
mov es,ax
mov di,0
cld ;把标志寄存器的DF位设置为0,正向传送
mov cx,(number-text)/2 ;以字为单位,传送的数目
rep movsw
;求得各个数位,放入0x07c0:number处
mov ax,number ;被除数
mov si,10 ;除数
mov cx,5 ;除法搞5次
mov bx,ax ;使用bx做偏移地址
digit:
xor dx,dx
div si
mov [bx],dl
inc bx
loop digit
;把求得的各个数位送到0xb800:di处
mov si,4 ;共5个数位,在number处
mov bx,number
mov ah,0x04 ;黑底红字
show:
mov al,[bx+si]
add al,0x30
mov [es:di],ax
add di,2
dec si ;si为0时,再减1导致符号位为1,配合jns终止循环
jns show ;(要紧跟dec si之后。。这样才能让jns根据si导致的SF变化生效)
mov word [es:di],0x0744 ;添加十进制标志D
jmp near $ ;$代表当前行汇编地址
times 510-($-$$) db 0 ;$$代表段首地址。除0xaa55两字节,填充满足总512字节
db 0x55,0xaa ;主引导扇区有效结束标志
编译后写入主虚拟磁盘的主引导扇区,运行虚拟机,得到如下图就成功了!笔者第一次并未成功,但通过Bochs调试,发现问题是dec si
没挨着jns show
,修改后就可以了。
参考资料
[1] 《x86汇编语言:从实模式到保护模式》李忠 著
[2] 《汇编语言》王爽 著