鱼C论坛

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

[汇编作业] 实验十

[复制链接]
发表于 2024-9-10 16:18:28 | 显示全部楼层 |阅读模式

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

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

x


  1. 1.
  2. assume cs:code
  3. data segment
  4.         db 'Welcome to masm!',0
  5. data ends

  6. code segment
  7. start: mov dh,8
  8.            mov dl,3
  9.            mov cl,2
  10.            mov ax,data
  11.            mov ds,ax
  12.            mov si,0
  13.            call show_str
  14.           
  15.            mov ax,4c00h
  16.            int 21h

  17. show_str: mov ax,0b800h   ;存显存地址
  18.                   mov es,ax
  19.                   
  20.                   sub dl,1        ;第三列相当于在2号位
  21.                   add dl,dl       ;字符是两个字节组成
  22.                   mov bl,dl      
  23.                   mov bh,0
  24.                   mov di,bx       ;转化为字节的列数
  25.                   
  26.                   sub dh,1        ;第8行相当于7号位行
  27.                   mov al,dh
  28.                   mov ah,0
  29.                   mov bx,00a0h    ;一行有160个字节
  30.                   mul bx          ;找到字节位置
  31.                   sub ax,1        ;减1得字属性位置
  32.                   mov bp,ax      
  33.                   
  34.         s:          mov cx,[si]     ;判断字符串末尾
  35.                   jcxz offset ok  ;cx为零停止
  36.               mov cl,2        ;字符绿色属性
  37.                   mov al,[si]     
  38.                   mov es:[bp+di+1],al    ;将字属性放入显存
  39.                   mov es:[bp+di+2],cl    ;将颜色属性放入字属性后一位
  40.                   
  41.                   add di,2               ;显存一个字符的单位
  42.                   add si,1               ;数据段一个字符单位
  43.                   
  44.                   jmp short s
  45.         ok:   ret                    ;提取字符串到末尾返回
  46. code ends
  47. end start

  48. 2.
  49. assume cs:code


  50. data segment
  51.    dd 0,0
  52. data ends

  53. code segment
  54. start: mov ax,data
  55.            mov ds,ax
  56.       
  57.            mov ax,4240h
  58.            mov dx,000fh
  59.            mov cx,0ah
  60.           
  61.            call divdw
  62.            mov ax,4c00h
  63.            int 21h
  64.           
  65.           
  66. divdw:mov bx,ax      
  67.           mov ax,dx
  68.           mov dx,bx               ;互换高低位
  69.           mov si,0
  70.           
  71.           mov [si+4],dx           ;将dx = 4240h暂存数据空间   00 00 00 00 42 40 00 00
  72.       div cl                  ;八位除数
  73.       mov bl,al               
  74.       mov bh,0
  75.           mov [si],bx             ;将高16位的商存数据空间      01 00 00 00 42 40 00 00
  76.           
  77.           mov dl,ah               ;余数存dx用于下一步16位除法  放入高16位相当于*65536
  78.           mov dh,0
  79.           
  80.           mov ax,[si+4]           ;将原公式低16被除数放入ax准备运算16除法
  81.           div cx                  ;运算后得到的ax既为结果低16位的商 86A0
  82.           mov cx,dx               ;dx为最终余数
  83.           mov word ptr dx,[si]    ;将数据空间内原本存储的高16位的商结合即为  186A0
  84.           ret

  85. code ends
  86. end start


  87. 3.
  88. assume cs:code

  89. data segment
  90.         dw 123,12666,1,8,3,38
  91. data ends

  92. d segment
  93.         db 5 dup(0)                 ;d段:开辟五个字节空间暂存字符串每个字符对应的字属性
  94. d ends

  95. stack segment
  96.         dw 2 dup(0)                 ;暂存计数器
  97. stack ends

  98. code segment
  99. start: mov ax,data              
  100.            mov ds,ax
  101.           
  102.            mov ax,0b800h            ;存显存段地址
  103.            mov es,ax
  104.           
  105.            mov ax,stack            
  106.            mov ss,ax
  107.            mov sp,4
  108.           
  109.            mov si,0
  110.            mov di,0

  111.            mov cx,6                 ;6个字符运行六次
  112.      s:push cx
  113.                                                                 ;避免cx被干扰
  114.            mov bx,0                 ;dtoc中 bx作为计数器为short计算位置
  115.            mov bp,0                 ;bp为d断寻址偏移
  116.            call dtoc
  117.           
  118.            add si,2                 ;dtoc中 si为data段中数值的偏移
  119.            mov bp,0                 ;show_str中  bp同样作为对d段暂存字符串字属性的使用
  120.            mov cx,bx                ;将dtoc得到的bx计数器作为show_str的循环次数,这样就知道要显示的数值到底是几位数
  121.            call show_str        
  122.            pop cx                   ;归还总体循环次数
  123.            loop s
  124.           
  125.            mov ax,4c00h
  126.            int 21h
  127.          
  128. dtoc:  mov ax,[si]
  129.        mov cx,10
  130.        mov dx,0
  131.        div cx                    
  132.        mov [si],ax
  133.        add dx,30h                ;当前dx为余数,即为数值最后一位的数字    +30h为对应的ascii码
  134.        mov ds:[bp+16],dl         ;倒序存入d段
  135.        dec bp
  136.       
  137.        inc bx                    ;计数器为show_str使用
  138.        mov cx,ax
  139.        jcxz short ok             ;字符末尾返回
  140.        jmp short dtoc
  141.       
  142. ok:    ret
  143.       
  144.       
  145. show_str: mov ax,5               ;d段为五个字节
  146.                   sub ax,cx              ;减去dtoc得到的计数器就可得知d段中有几个字属性,从哪个字节开始将数据传入显存
  147.                   mov bp,ax              
  148.                   mov al,ds:[bp+12]      
  149.                   mov ah,2
  150.           mov es:[di+1830],ax    ;1830为屏幕显示位置
  151.           add di,2
  152.           loop show_str
  153.           add di,2               ;空格隔开
  154.           ret

  155. code ends
  156. end start
  157.                   
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-9-10 16:29:56 | 显示全部楼层
看起来你在求助于两个不同的汇编程序,分别是一个字符串显示程序和一个双字除法程序。让我来帮助你完成这些程序,并解决其中存在的问题。

### 第一部分:字符串显示程序
目标是在特定的屏幕位置显示字符串 "Welcome to masm!"。

我们将从代码中的错误入手进行分析和修正:

1. `show_str` 子程序中缺少字符串长度的初始化。
2. 需要赋值 `es:[di]` 处的显存地址。
3. `cx` 应该在每次循环之后递减。

修正后的代码如下:

  1. assume cs:code
  2. data segment
  3.     db 'Welcome to masm!',0
  4. data ends

  5. code segment
  6. start:
  7.     mov ax, data
  8.     mov ds, ax
  9.     mov dh, 8
  10.     mov dl, 3
  11.     mov si, offset data        ; si 初始化为字符串的起始地址
  12.     call show_str
  13.    
  14.     mov ax, 4C00h
  15.     int 21h

  16. show_str:
  17.     mov ax, 0b800h            ; 显存地址
  18.     mov es, ax
  19.     sub dh, 1                 ; 转化为实际行(显示从第7行开始)
  20.     sub dl, 1                 ; 转化为实际列(显示从第2列开始)
  21.     shl dl, 1                 ; 每个字符占两个字节
  22.     mov di, dx                ; di = dh * 160 + dl*2
  23.     shl dh, 7
  24.     shl dh, 1
  25.     add di, dh
  26.    
  27.     mov cx, 16                ; 假设字符串长度为16,包括结束符
  28. s:
  29.     mov al, ds:[si]
  30.     cmp al, 0                 ; 检测字符串结尾
  31.     je ok
  32.     mov es:[di], al
  33.     mov es:[di + 1], 2        ; 设置颜色为绿色
  34.     add di, 2
  35.     inc si
  36.     loop s
  37. ok:
  38.     ret
  39. code ends
  40. end start
复制代码


### 第二部分:双字除法程序
此程序旨在实现 32 位除法,即 42400h 除以 0Ah。

我们来修复并完成这部分代码:

  1. assume cs:code
  2. data segment
  3.    result dd 0
  4. data ends

  5. code segment
  6. start:
  7.     mov ax, data
  8.     mov ds, ax

  9.     mov ax, 4240h
  10.     mov dx, 0000h
  11.     push dx                  ; 模拟 4240h 在高位
  12.     push ax                  ; 模拟 0000h 在低位
  13.     pop ax
  14.     pop dx

  15.     mov cx, 0Ah              ; 除数
  16.     call divdw
  17.    
  18.     mov ax, 4C00h
  19.     int 21h
  20.       
  21. divdw:
  22.     mov ebx, edx: eax        ; 将 ax 和 dx 组合成 32 位(edx: eax)
  23.     xor edx, edx
  24.     div cx                   ; 执行 32 位除法,quotient 在 eax, remainder 在 edx
  25.     mov ds: result, eax      ; 存储结果
  26.     ret

  27. code ends
  28. end start
复制代码

修正说明:
1. 我们先将 `ax` 和 `dx` 扩展成 32 位寄存器 `edx:eax`。
2. 再执行 `div` 指令。

如果两个问题都已解决或如果有进一步问题,请告诉我。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-18 14:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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