计算FFFF:0 ~ FFFF:B单元中数据的和,结果存储到dx中
1 分析与解决
- 内存单元:字节型数据
- 目标寄存器:dx,字型寄存器,不匹配
- 数据范围:dx不会超,但是dl会超,因此必须用dx
- 将字节型数据,转换为字型数据,前8位置为0
- 利用循环,和bx的增加,实现寻址和累加
assume cs:codesg
codesg segmentstart:; 数据指向 ffff:0mov ax,0ffffhmov ds,axmov bx,0mov dx,0 ; 累加器置零mov cx,12 ; 设置循环次数mov ah,0 ; 高8位置零,接收字节型数据s:mov al,[bx]add dx,axinc bxloop smov ax,04c00hint 21h
codesg ends
end start
需要注意,mov ah,0
放在循环里面第一条也可以,但是没有必要!(除非指令是乱序执行的)
2 重要知识点
2.1 框架一:定位数据地址
mov ax,段地址
mov ds,ax
mov 目标,偏移地址
2.2 框架二:累加先置零
累加器在进行运算前,要先置零
mov dx,0
2.3 框架三:字节型数据转换为字型数据
mov ah,0
mov al,字节型数据
这样,字节型数据,就成了存储在ax中的字型数据
2.4 框架四:循环结构
mov cx,循环次数
s:<内容>loop s
2.5 框架五:利用自增实现批量处理
利用循环结构实现寄存器的自增,这样就可以批量处理处于连续内存的数据了。
3 结合C语言和x86-32汇编
循环的本质,是指令的跳转,例如上面的loop
,本质是修改IP的值,使得CS:IP
指向对应的指令,8086使用cx的值来控制循环次数。
看一下C语言的循环
int i = 0;
while (i < 10) {i++;
}
对应的x86-32汇编指令
1: int i = 0;
00FE1728 mov dword ptr [ebp-8],0 2: while (i < 10) {
00FE172F cmp dword ptr [ebp-8],0Ah
00FE1733 jge 00FE1740 3: i++;
00FE1735 mov eax,dword ptr [ebp-8]
00FE1738 add eax,1
00FE173B mov dword ptr [ebp-8],eax 4: }
00FE173E jmp 00FE172F
依然秉承着原有的思想:循环的本质是跳转,循环次数靠条件控制。
这里简单解释:
cmp是比较指令,compare,比较两个操作数的大小,得到的结果,它不改变操作数,但会影响标志寄存器的值。
jge是转移指令,用于修改EIP的值,用于指令的跳转,它常与cmp一起出现,它根据标志位的情况,判断是否执行跳转。
jmp是无条件跳转指令,遇到就立即跳转。
这里没有阐明技术细节,只是宏观认知,以下是while循环的图示: