鱼C论坛

 找回密码
 立即注册
查看: 117|回复: 1

[技术交流] 关于实验10(3)

[复制链接]
发表于 2025-3-4 16:45:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
    实验10(3)我用了1天多的时间才搞定,也没看答案,原因有二:一是自己的思路容易受答案思路干扰,二是看答案就必须按照答案思路去理解,也很累人的。
自己搞定之后再看答案比较,应该更容易理解答案。当然,最关键的是要自己能做出来,至于思路是不是简介并不重要,因为随着经验增加,对汇编语言的理解
会越来越深,思路自然会越来越精。
    开始时,本人试图把数据段同时当作栈段,但是因为后续思路没厘清,就放弃了。本人的方法是基于知道12666这个数的位数来弄的。
    现把本人代码共享。下一步是考虑问题扩展,即把12666扩大到32bit位数据,使用dx和ax联合存储,数字不固定。



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;8行
                        mov dl,3;3列
                        mov cl,2;字符属性
                       
                        call show_str

                        mov ax,4c00h
                        int 21h
               
dtoc:                mov si,5  ;用来指向字节数据偏移地址,初始指向索引位置5,然后从索引位置4开始依次向低地址存放数字
                        mov bx,10  ;设置除数10给bx,每次去除被除数,取余数即为要的数字
                       
                        mov cx,5  ;设置循环次数
                       
        s:                ;考虑到al长度可能不够保存商,所以被除数用dx+ax保存,除数用bx保存
                        ;因为偏移地址从0索引开始,而当cx=0时循环结束。为了保证存储次数和
                        ;循环次数一致,所以,si初始值为5,开始循环时,先把si自减一次。
                        dec si;
                        mov dx,0
                        div bx  ;除法结果:ax存商,也即是下一步的被除数,dx保存余数,即要取的数字
                        add dl,30h  ;因为余数是一位数字,保存在dx寄存器的低8位dl中。再加30h转化为对应的ASCII码
                        mov ds:[si],dl;
                        loop s
                        ret
                       
show_str:        mov ax,0b800h  ;把显示段给附件段
                        mov es,ax
                       
                        mov al,160  ;计算显示段偏移地址
                        mul dh
                        mov si,ax  ;此时si中存储的是第8行的首地址
                        mov al,2  ;每列占2个字节。计算3列的偏移地址,为方便下面传值,直接把3列的偏移地址加到si上
                        mul dl  ;dl中存储的是列数3
                        add si,ax  ;si定位到显示段的第8行第3列
                       
                        mov al,cl  ;因下面要用到cx,所以先把cl中存的字符属性值给al
                        mov di,0  ;指向数据段起始字节偏移地址
                        mov cx,5  ;循环次数,把数字字符ASCII码移入显示段,同时赋予字符属性为2
                       
        t:                push cx
                        mov dl,ds:[di]
                        mov es:[si],dl  ;存入数字ASCII码
                        mov es:[si].1,al  ;存人字符属性
                        inc di
                        add si,2
                        pop cx
                        loop t
                       
                        ret
code ends

end start
               


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-3-4 16:46:54 | 显示全部楼层
关于实验10(3)的代码分享与改进建议

感谢您分享关于实验10(3)的代码及思路!看得出您已经花了不少时间和精力去解决这个问题,并且有了自己的见解。下面我对您的代码和描述做一些整理并给出改进建议。

主要代码功能:

  • 将数字12666转换为字符并存储。
  • 在屏幕的第8行第3列显示这些字符。


代码注释与调整建议:

1. 使用更清晰的变量名可以提高代码的可读性。
2. 在dtoc转换过程中,可以考虑支持更大范围的数字。

以下是对原代码的结构化整理与注释:
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 ax, 4c00h    ; 正常退出
    int 21h

dtoc:
    mov si, 5        ; 偏移地址指向转换结果末尾
    mov bx, 10       ; 商的除数
    mov cx, 5        ; 最大循环次数

convert_loop:
    dec si
    mov dx, 0
    div bx          ; AX除以BX, 余数在DX,商在AX
    add dl, 30h     ; 转换余数为ASCII字符并存储
    mov ds:[si], dl
    loop convert_loop
    ret

show_str:
    mov ax, 0b800h   ; 显存段地址
    mov es, ax

    mov al, 160      ; 计算第8行起始地址
    mul dh
    mov si, ax
    mov al, 2
    mul dl
    add si, ax       ; 确定显示偏移地址

    mov al, cl       ; 获取字符属性
    mov di, 0        ; 数据段起始偏移地址
    mov cx, 5        ; 显示字符个数

display_loop:
    push cx
    mov dl, ds:[di]
    mov es:[si], dl  ; 显示字符
    mov es:[si+1], al; 设定字符属性
    inc di
    add si, 2
    pop cx
    loop display_loop
    ret
code ends

end start

进一步扩展:可以考虑将dtoc函数改进以支持32位数字转换。例如,可以分别处理dx和ax,以处理最大位数。

再次感谢您的分享,希望对您进一步的扩展和理解有帮助!如果有任何问题,请随时询问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-3-31 08:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表