; ------------------------------------------------------------------------
; 显示 AL 中的数字
; 默认地:
; 数字已经存在 AL 中
; edi 始终指向要显示的下一个字符的位置
; 被改变的寄存器:
; ax, edi
; ------------------------------------------------------------------------
DispAL:
push ecx
push edx
mov ah, 0Ch ; 0000: 黑底 1100: 红字
mov dl, al
shr al, 4
mov ecx, 2
.begin:
and al, 01111b
cmp al, 9
ja .1
add al, '0 '
jmp .2
.1:
sub al, 0Ah
add al, 'A '
.2:
mov [gs:edi], ax
add edi, 2
mov al, dl
loop .begin
add edi, 2
pop edx
pop ecx
ret
; DispAL 结束-------------------------------------------------------------
gs指向显存
; ------------------------------------------------------------------------
DispReturn:
push eax
push ebx
mov eax, edi
mov bl, 160
div bl
and eax, 0FFh ; 为什么要用ADD????
inc eax
mov bl, 160
mul bl
mov edi, eax
pop ebx
pop eax
ret
; DispReturn 结束---------------------------------------------------------
------解决方案--------------------------------------------------------
andeax, 0FFh ; 为什么要用ADD????
不是ADD,而是AND,目的是去处显存地址中的高字,保留低字,因为AL中存放的是商,AH中存放的是余数。下面还有用这个“(商+1)*160” 来计算换行后的首字符地址。不过这个换行过程存在隐患,当过程的入口参数edi的实际值大于65536时,此过程将不再能正常工作!因为这个过程假设edi的低字有效。
------解决方案--------------------------------------------------------
al是八位寄存器,可以存储2个16进制位,例如AL=5F。
andal, 01111b 执行后al=0F。
下面的判断是:
if(al> 9)
al=al+31 ;转化为字母(F)为ASCII码
else
al=al+30 ;转化数字为ASCII码
subal, 0Ah
addal, 'A '
就等于
add al,31
mov[gs:edi], ax; 写入显存
addedi, 2 ; 移动显存指针
movdl, al ;目的是保持AL的低半字节
第一次执行循环体前shral, 4是为了先转化高半字节
自己好好研究一下