第九章 转移指令的原理

实验8:分析一个奇怪的程序

assume cs:codesg

codesg segment
        mov ax, 4c00H
        int 21H
start:  mov ax, 0
    s:  nop
        nop
        mov di, offset s
        mov si, offset s2
        mov ax, cs:[si]
        mov cs:[di], ax
    s0: jmp short s
    s1: mov ax, 0
        int 21H
        mov ax, 0
    s2: jmp short s1
        nop
codesg ends
end start

分析下面程序,在运行前思考:这个程序可以正确返回吗?运行后思考:为什么是这样的结果?通过这个程序加深对相关内容的理解.

解:

  1. 程序根据从start处开始执行。nop命令占用一个字节,会被CPU执行,只是什么都不做(No operation)。
  2. nop下 - s0前的四条指令意为:将s2处的指令的机器码,注意是机器码,是机器码值存储到s处的两个字节(两个nop)。
  3. 程序执行到s0处时,jmp跳转到s处,执行。
    1. 执行的是什么?s2处的指令jmp short s1的机器码
    2. 机器码是多少?即为位移量值。即IP寄存器需要根据此进行变更值,跳转指定位置执行的代码。
    3. 位移值是多少?-10(补码形式存储),00001010(源码)>> 11110101(取反)>> 11110110(加一)>> F6H(转16进制后)
    4. 如何计算出的-10?需要跳转的标号处的指令的偏移量 - jmp指令后的第一个字节的偏移量。
    5. 为什么是减去jmp命令后的一个字节的偏移量?回顾第二章:2.10节的指令的执行流程(下面有总结描述),IP寄存器的值增加指令机器码数据的长度数 发生在执行指令前。所以执行EB(jmp指令对应的机器码)跳转时,IP已经增加了。故要以jmp指令后的一个字节的偏移量为基准,计算位移值。
    6. 执行后IP指向了哪里?代码段的第一行:mov ax, 4c00H。
    7. 位移量为负数时,也是从jmp指令后的一个字节的偏移量为基准,进行移动吗?是的,位移量多加上jmp指令的长度呗。

指令的执行流程:

  1. 根据指令地址通过地址加法器计算出20位内存地址
  2. 通过20位地址总线找到存需要执行的指令的机器码的内存存储单元
  3. 通过数据总线将指令的机器码写入CPU的指令缓冲器
  4. IP寄存器的值增加指令机器码数据的长度数
  5. 执行机器码
  6. 回到第一步再次执行流程

实验9:根据材料编程

编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串:“welcome to masm!”

实现代码:

assume cs:codesg,ds:data

data segment
	db 'welcome to masm!' ;16b
	db 02H,24H,71H ; 绿色:00000010(02H);绿底红色:00100100(24H);白底蓝色:01110001(71H)
codesg segment
start:
	; 输入数据源
	mov ax,data
	mov ds,ax
	; 显存 & 写入的内存位置``
	mov ax,0B800H
	mov es,ax
	mov bx,1824 ; 1760 + 64

	; 字符的属性数据位置
	mov si,16

	mov cx,3
count:
	push cx
	mov cx,16
	mov di,0
write:
	; read char
	mov al,ds:[di]
	; write char
	mov es:[bx],al
	; write char attributes
	mov al,ds:[si]
	mov es:[bx+1],al

	inc di
	add bx,2
	loop write
	
	inc si
	add bx,128
	pop cx
	loop count

	mov ax, 4c00H
	int 21H
codesg ends

end start

总的来说,除了阅读材料外,没有新的内容。巩固数据的内存定位,与寄存器的使用分配。

复习下已学的寄存器的不同用途(未学:bp、psw):

  1. ds/es段寄存器用于读取内存数据。
  2. bx/di/si可以参与内存定位,作为偏移量,其他的寄存器不可。
  3. 循环控制只能使用cx。
  4. 除法运算时只会用到ax/dx。
  5. ss段寄存器存储着栈的内存起始位置,sp寄存器记录着push存储数据时的偏移量。
  6. cs段寄存器存储需要的执行机器码的内存起始位置,ip寄存器存储着下一条执行机器码的偏移量。

2022.04.30补充

关于bp寄存器:

  1. bp也可以参与内存定位。bx、bp、si、di可以单独,或者以4中组合的形式出现在[]中
    1. [bx+si] | [bx+di] | […+idata]
    2. [bp+si] | [bp+di] | […+idata]
    3. 错误的:[si+di] | [bx+bp]
  2. 若在[]中使用bp寄存器,且没有显示的给出段地址,则段地址默认在ss中。就如[] 中使用bx寄存器,段地址默认在ds中。例:
    1. mov ax,[bp] = (ax) = ((ss)*16 + (bp))
    2. mov ax,[bp+si] = (ax) = ((ss)*16 + (bp) + (si))
    3. mov ax,[bp+si+idata] = (ax) = ((ss)*16 + (bp) + (si) + (idata))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值