|
|
8086汇编实验十第三题
学习笔记
8086汇编实验十第三题
assume cs:code
data segment
db 10 dup(0)
data ends
code segment
start:
mov ax,12666 ;定义将要显示的数据
mov bx,data
mov ds,bx
mov si,0
call dtoc ;子程序,将二进制信息转变为十进制字符串
mov dh,8
mov dl,3
mov cl,2 ;定义字符串目标地址行数、列数、颜色属性
call show_str ;子程序,将字符串显示在目标位置
mov ah,00h
int 16h
mov ax,4c00h
int 21h
dtoc: ;将二进制信息转变为十进制字符串,子程序开始
push dx
push cx
push ax
push si
push bx ;保存原始数据
mov bx,10 ;方便后面数字除10
mov dx,0 ;dx归零,方便后续计算
push dx ;栈段结尾置入0,方便后续结束循环
s0: div bx ;ax为商,dx为余数且必定小于10
add dl,30h ;将余数转化为十进制字符,8位
push dx ;将十进制字符压入栈,8位
mov dx,0
mov cx,ax ;将商置入cx,检查cx是否为零,余数为零则跳出循环
jcxz s1
jmp short s0 ;子程序,将十六进制数转化为十进制
s1: pop
mov cx, ;字符串置入数据段,数据为0时,跳出循环
inc si
jcxz ok0
jmp short s1 ;子程序,将十进制字符串置入数据段ds
ok0: pop bx
pop si
pop ax
pop cx
pop dx ;将原始数据送回原寄存器
ret ;将二进制信息转变为十进制字符串,子程序结束
show_str: ;字符串显示,子程序开始
push cx
push si ;程序开始,cx、si压栈,保存主程序数据以及颜色属性
mov ax,0b800h
mov es,ax ;定义字符串目标段地址
mov al,160
dec dh ;地址从零开始计算,所以减一
mul dh
mov bx,ax ;计算目标地址偏移行数所占字节数
mov al,2
mul dl
sub ax,2 ;地址从零开始计算,减一,偶数字节存放字符,再减一
add ax,bx ;计算目标地址偏移列数所占字节数,加上偏移行数所占字节
mov di,ax ;设置字符串目标偏移地址,获得目标首地址
mov al,cl ;保存颜色属性,因为后面需要跳转结束程序需要用cx
s: mov ch,0
mov cl, ;ds:指向字符串,判断是否可以结束循环
jcxz ok ;指向结尾0时,跳转结束程序
mov es:,cl ;将data中的字符串送入目标地址
mov es:,al ;送入颜色属性
inc si
add di,2 ;数据源地址+1,目标地址+2,准备下一次循环
jmp short s ;无条件跳转,回到循环程序开头
ok: pop si
pop cx ;程序结束,将保存的数据出栈
ret ;字符串显示,子程序结束
code ends
end start
你好!你的代码思路基本正确,但在 dtoc 和 show_str 子程序中有几处指令不完整,缺少操作数。下面我为你指出问题并提供修正后的代码。
主要问题:
1. 在 dtoc 的 s1 标签处,pop 指令需要指定寄存器(如 dx),且 mov cx, 需要操作数来检查弹出的值。
2. 在 show_str 的 s 标签处,mov cl, 需要从数据段读取字符,且 mov es:,cl 和 mov es:,al 需要指定目标偏移地址(如 es:[di])。
修正后的完整代码如下:
- assume cs:code
- data segment
- db 10 dup(0)
- data ends
- code segment
- start:
- mov ax, 12666 ; 要转换的数字
- mov bx, data
- mov ds, bx
- mov si, 0
- call dtoc ; 调用转换子程序
- mov dh, 8 ; 行号(1-based)
- mov dl, 3 ; 列号(1-based)
- mov cl, 2 ; 颜色属性(绿色)
- call show_str ; 调用显示子程序
- mov ah, 00h ; 等待按键
- int 16h
- mov ax, 4c00h ; 退出程序
- int 21h
- ; 子程序:dtoc
- ; 功能:将word型数据转换为十进制字符串,字符串以0结尾
- ; 参数:ax = 要转换的数字,ds:si 指向字符串存储区
- dtoc:
- push dx
- push cx
- push ax
- push si
- push bx ; 保存寄存器
- mov bx, 10 ; 除数10
- mov dx, 0 ; 清除dx,用于除法
- push dx ; 压入0作为字符串结束标志
- s0:
- div bx ; ax = 商,dx = 余数
- add dl, 30h ; 余数转换为ASCII码
- push dx ; 压入ASCII码
- mov dx, 0 ; 清除dx,为下一次除法准备
- mov cx, ax ; 检查商是否为0
- jcxz s1 ; 如果商为0,跳转到s1
- jmp short s0 ; 继续循环
- s1:
- pop dx ; 弹出ASCII码到dx
- mov [si], dl ; 存入数据段
- inc si ; 指向下一个字节
- mov cx, dx ; 检查dx是否为0(结束标志)
- jcxz ok0 ; 如果为0,结束循环
- jmp short s1 ; 继续弹出
- ok0:
- pop bx
- pop si
- pop ax
- pop cx
- pop dx ; 恢复寄存器
- ret
- ; 子程序:show_str
- ; 功能:在指定位置显示字符串
- ; 参数:dh = 行号(1-25),dl = 列号(1-80),cl = 颜色属性,ds:si 指向字符串首地址
- show_str:
- push cx
- push si ; 保存寄存器
- mov ax, 0b800h
- mov es, ax ; 设置显存段地址
- ; 计算行偏移:偏移 = (行号 - 1) * 160
- mov al, 160
- dec dh ; 行号转换为0-based
- mul dh ; ax = dh * 160
- mov bx, ax ; 保存行偏移
- ; 计算列偏移:偏移 = (列号 - 1) * 2
- mov al, 2
- mul dl ; ax = dl * 2
- sub ax, 2 ; 转换为0-based列偏移
- add ax, bx ; 加上行偏移,得到总偏移
- mov di, ax ; di 指向显存中的目标位置
- mov al, cl ; 保存颜色属性到al
- s:
- mov ch, 0
- mov cl, [si] ; 读取字符到cl
- jcxz ok ; 如果字符为0,结束循环
- mov es:[di], cl ; 写入字符到显存
- mov es:[di+1], al ; 写入颜色属性到显存
- inc si ; 指向下一个字符
- add di, 2 ; 指向下一个显存位置(字符+属性)
- jmp short s
- ok:
- pop si
- pop cx ; 恢复寄存器
- ret
- code ends
- end start
复制代码
关键修正说明:
1. dtoc 子程序中:
- s1: pop dx:弹出ASCII码到dx。
- mov [si], dl:将ASCII码存入数据段(只取低8位)。
- mov cx, dx:检查dx是否为0(结束标志)。
2. show_str 子程序中:
- mov cl, [si]:从数据段读取字符。
- mov es:[di], cl 和 mov es:[di+1], al:正确写入字符和属性到显存。
这样,程序就能正确将12666转换为字符串"12666"并显示在屏幕第8行第3列了。如果有任何疑问,欢迎继续提问!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 |
|