先贴代码
start: ;//标号(冒号可去)
mov ax, 65535
xor dx, dx ;等价于mov dx, 0(寄存器间操作更快)
mov bx, 10
div bx ;//ax/bx==65535/10 ax=商(65535), dx=余数(5)
add dl, 0x30 ;//(0x30是16进制的"0"字符)
;//将数字转换为对应的数字字符存到dl中
;//(此处dl是dx的低八位)
mov cx, 0 ;//将段地址0传送到数据段ds
mov ds, cx ;//不能直接传,要借助寄存器传
mov [0x7c00+buffer], dl
;//将dl中的字符编码传送到ds段内的偏移地址处(也就是buffer第一个0)
;//dl为8位长度,以字节单位进行
xor dx, dx ;//dx中内容已保存,清零dx
div bx
add dl, 0x30
mov [0x7c00+buffer+1], dl
;//将dl中的字符编码传送到ds段内的偏移地址加一处(也就是buffer第二个0)
xor dx, dx
div bx
add dl, 0x30
mov [0x7c00+buffer+2], dl
;//将dl中的字符编码传送到ds段内的偏移地址加二处(也就是buffer第三个0)
xor dx, dx
div bx
add dl, 0x30
mov [0x7c00+buffer+3], dl
;//将dl中的字符编码传送到ds段内的偏移地址加三处(也就是buffer第四个0)
xor dx, dx
div bx
add dl, 0x30
mov [0x7c00+buffer+4], dl
;//将dl中的字符编码传送到ds段内的偏移地址加四处(也就是buffer第五个0)
buffer: ;//标号(冒号可去)
db 0,0,0,0,0
current: ;//标号(冒号可去)
times 510-(current-start) db 0
db 0x55, 0xaa
除操作div
如果在指令中指定的是8位寄存器或8位操作数的内存地址,
则意味着被除数在寄存器AX中,相除后商在寄存器AL里余数在寄存器AH里
列:
___________
|___________| 2002
div bh ;bh是位寄存器
div byte [0x2002] ;byte一个字节
如果在指令中指定的是16位寄存器或16位操作数的内存地址,
则意味着被除数是32位的,相除后商在寄存器AX里余数在寄存器DX里
列:
___________
|___________|
|___________| 2002
div bx ;被除数是32位的
div word [0x2002] ;word一个字(两个字节)
如果在指令中指定的是32位寄存器或32位操作数的内存地址,
则意味着被除数是64位的,相除后商在寄存器EAX里余数在寄存器EDX里
列:
___________
|___________|
|___________|
|___________|
|___________| 2002
div ebx ;(EAX与EDX组合成一个64位的被除数除以ebx的内容)
div dword [0x2002] ;dword两个字(四个字节)
如果在指令中指定的是64位寄存器或64位操作数的内存地址,
则意味着被除数是128位的,相除后商在寄存器RAX里余数在寄存器RDX里
列:
___________
|___________|
|___________|
|___________|
|___________|
|___________|
|___________|
|___________|
|___________| 2002
div rbx
div qword [0x2002] ;dword四个字(八个字节)
异或操作xor (0与0=0 0与1=1 1与0=1 1与1=0)
xor r/m r/m/imm
;r代表寄存器,m代表内存地址,imm代表立即数(两个数据长度必须相同)
列:
xor ax, 3 ;把3当作16位
xor word [0x2002], 67 ;把67当作16位
xor si, [0x2002] ;从[0x2002]中读取一个16位再进行异或
加操作add
add r/m r/m/imm
传送到显存
mov al, [0x7c00+buffer+4]
mov cx, 0xb800 ;//将ds段寄存器改为显存的地址
mov ds, cx
mov [0x00], al ;//[0x00]相对0xb800偏移地址
mov byte [0x01], 0x2f
-------------------------------------------------------------
mov cx, 0
mov ds, cx ;//将ds段地址改为原来的以便取数字字符
mov al, [0x7c00+buffer+3]
mov cx, 0xb800
mov ds, cx
mov [0x02], al
mov byte [0x03], 0x2f
...
... ;//重复取完
以上代码较为麻烦
所以我们借用附加寄存器es完成操作,代码如下:
mov cx, 0xb800
mov es, cx
mov al, [0x7c00+buffer+4]
mov [es:0x00], al ;//"es:"是段超越前缀
mov byte [es:0x01], 0x2f ;//0x2f是颜色属性指令
mov al, [0x7c00+buffer+3]
mov [es:0x02], al ;//"es:"是段超越前缀
mov byte [es:0x03], 0x2f ;//0x2f是颜色属性指令
mov al, [0x7c00+buffer+2]
mov [es:0x04], al ;"es:"是段超越前缀
mov byte [es:0x05], 0x2f ;0x2f是颜色属性指令
mov al, [0x7c00+buffer+1]
mov [es:0x06], al ;"es:"是段超越前缀
mov byte [es:0x07], 0x2f ;0x2f是颜色属性指令
mov al, [0x7c00+buffer]
mov [es:0x08], al ;"es:"是段超越前缀
mov byte [es:0x09], 0x2f ;0x2f是颜色属性指令
again:
jump again ;//一直循环
加上段超越前缀就是以es作为段地址,没加就是以ds为准
编译后 将bin文件写入虚拟硬盘
打开bochs调试如图所示
至此结束