段的起始地址总是16的倍数,设段中数据占N字节,那么段的大小为(N/17+1)/16字节
CPU执行指令(如果end 之后没有标号的话)默认是从伪代码后第一行指令开始,有标号后会从用户指定的指令开始执行
and al, 10111111B:将第6位设置成0,其余位不变
or al, 01000000B:将第4位设置成1,其余位不变
' '符号来定义字符,例如 db 'UNIX'
db,dw,dq(4字)这些都是伪指令,只给编译器识别
那么其在内存中分布情况为:
mov ax, ‘a’ 把a对应的ASCII码'61H'赋值给ax
ASCII编码的一个字符占1字节,但实际大小只有7位,unicode编码占4字节
[bx+idata]表示有时更方便,例如:
① A,B,C,D,E ② a,b,c,d,e 将①中数据变小写,②变大写
如果没有[bx+idata]写的话:用两个循环,一个改成小写,一个改成大写
一个循环:
ds:[bx]将A变成a,之后写成ds:[bx+5]将a变成A
si寄存器和di寄存器类似于bx寄存器,可以保存内存地址,但是前两者无法分成高低8位
到此,内存单元可以表示成
[ds+si+idata],[bx+si],[bx+idata],[bx].idata,idata[bx],[bx].idata[si]
(寄存器和寄存器)
;用来表达注释
cx寄存器表达数据范围为0 - (2^16) - 1 所以一旦0 减去 1后结果会变成FFFFH((2^16) - 1)
对于多层循环,要注意cx寄存器的使用,内层循环会覆盖掉外层循环的cx寄存器值
解决方法:
进入内层循环前,先将cx数据保存在栈中,等到退出内层循环中,再pop将cx恢复到外层循环状态
只有bx,bp,si,di用在表示内存单元,配合使用规则:
bx与si , bx与di,bp与si,bp与di 可以配合使用
bx与bp,si与di 均不可以
bp寄存器相当于sp寄存器,对于[bp]这样表示,那么默认的段地址在sp寄存器中,但可以显式指定段前缀:例如ds:[bp],cs:[sp]
对于mov ax,1指令,其中的立即数1,直接反映在该指令对应的机器码中,对于指令则放在指令缓冲器中
指明处理数据长度:
①寄存器指明 :mov ax, [1]内存偏移地址为1的字型数据,al则为字节型数据
②xxx ptr
mov word ptr ds:[0], 1(1当成字型数据)
mov byte ptr ds:[0], 1(1当成字节数据)
③默认长度
push和pop都是字型数据
对于类似于结构体bx中,idata为结构体中某数据项,si为某数据项为数组中的元素:
那么定位该元素可以表达成[bx].idata[si] = [bx+idata+si]
div指令执行除法:
①除数为8位,则被除数为16位保存在ax中,结果商放在al中,余数放在ah中
②除数为16位,则被除数为32位保存在dx(高16位)和ax(低16位)中,结果商放在ax中,余数放在dx中
为什么除数n位,被除数就要2*n位?
因为CPU总是用加法来模拟其他运算,例如乘法2*3用2+2+2模拟,那么也用乘法模拟除法,例如9/4,4*1 < 9,那么再用4 * 2 < 9,直到4 * 3 > 9结束,返回前一步,知道结果为2,余数为9 - 2*4 =1,这就要求被除数要比除数大来防止检验过程中数据溢出
除法过程:
div bx:除数bx为16位,所以被除数要32位:
(ax) = ((dx)*10000H + (ax))/(bx)的商
(dx) = ((dx)*10000H + (ax))/(bx)的余数
div byte ptr ds:[0]:byte ptr指明除数为8位,所以被除数为16位:
(al) = (ax)/((ds)*16 + 0)的商
(ah) = (ax)/((ds)*16 + 0)的余数
div word ptr ds:[0]:word ptr指明除数为16位,所以被除数为32位:
(ax) = ((dx)*10000H + (ax))/((ds)*16 + 0)的商
(dx) = ((dx)*10000H + (ax))/((ds)*16 + 0)的余数
为什么dx要乘以10000H?
10000H = 16^4D,在十六进制下,即数据左移4位,后面多出来的4个0刚好给ax内容
dd = define double word(32bit)
实现64位功能条件:64位CPU,64位OS,64位软件,当中少一项都为32位
dup指令:
db 3 dup(0):定义3字节,且内容都为0
db 4 dup(0,1,2):定义9字节,内容为0,1,2,0,1,2,0,1,2
Done!!!