从实模式到保护模式笔记03比高斯更快的计算

从实模式到保护模式笔记03比高斯更快的计算

0x00 代码

jmp near start
message db '1+2+3+...+100='
start:
mov ax,0x7c0;设置数据段基地址
mov ds,ax

mov ax,0xb800;
mov es,ax

mov si,message
mov di,0
mov cx,start-message
print:
mov al,[si]
mov [es:di],al
inc di
mov byte [es:di],0x07
inc di
inc si
loop print

xor ax,ax
mov cx,1
s:
add ax,cx
inc cx
cmp cx,100
jna s

xor cx,cx
mov ss,cx
mov sp,cx

mov bx,10
xor cx,cx

s1:
inc cx;记录位数
xor dx,dx
div bx
add dl,0x30;求得的余数即使对应的位的10进制,+0x30变成对应的ascii
push dx
cmp ax,0
jne s1

s2:
pop dx
mov [es:di],dl
inc di
mov byte [es:di],0x07
inc di
loop s2;根据之前记录在cx里的位数决定循环次数

jmp near $;原地循环
times 510-($-$$) db 0
db 0x55,0xaa

QQ截图20200628213544

0x01 代码讲解

​ 这章就没啥可讲的了,就一个栈,xor cx,cx mov ss,cx mov sp,cx那么push的第一条数据将被放在0x0000:0xfffe处(等效于sp=sp-2 mov [ss:sp],x)。

​ bochs中有print-stack命令,可以查看栈顶以下的16个字的内容(也就是[ss:sp]-[ss:sp+31])

QQ截图20200628214606

​ 本章大部分都在讲寻址方式,寻址方式就是指如何找到要操作的数据:

​ 寄存器寻址 mov ax,cx

​ 立即数寻址 mov ax,1

​ 内存寻址 mov ax,[0x00] mov ax,[bx+0x00] mov ax,[bx+si] mov ax,[bx+si+0x00]

0x02 题目检测

QQ截图20200628215114

​ 1.31-37行代码如下:

xor ax,ax
mov cx,1
s:
add ax,cx
inc cx
cmp cx,100
jna s

​ 要cx既用来控制循环还要用来用来作为被累加的数(也就是从1变到100),那就只能用栈了,进循环后push保存,出循环出栈恢复:

xor ax,ax
mov cx,100
s:
push cx
sub cx,100
neg cx
inc cx
add ax,cx
pop cx
loop s

QQ截图20200628220344

2计算1-1000的和,1+2+。。+1000结果是(1+1000)*1000/2=500500»65535,所以16位的寄存器放不下,题目明示我们要用adc实现32位加法:

xor ax,ax
xor dx,dx
mov cx,1
s:
add ax,cx
adc dx,0
inc cx
cmp cx,1000
jna s
jmp near $
times 510-($-$$) db 0
db 0x55,0xaa

QQ截图20200628221515

​ 500500换成16进制即0x7a314,上述代码运行正确