《x86汇编语言:从实模式到保护模式》(第6章---相同的功能,不同的代码)

第五章的代码很多地方是手动写死的,本章就是要利用新的汇编知识改写第五章的代码,变的更加灵活和简洁。
在这里插入图片描述
图 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] 《汇编语言》王爽 著

发布了323 篇原创文章 · 获赞 193 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/ccnuacmhdu/article/details/103563432
今日推荐