鱼C论坛

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

[汇编作业] 实验十

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

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

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

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

code segment
start: mov dh,8
           mov dl,3
           mov cl,2
           mov ax,data
           mov ds,ax
           mov si,0
           call show_str
           
           mov ax,4c00h
           int 21h

show_str: mov ax,0b800h   ;存显存地址
                  mov es,ax
                  
                  sub dl,1        ;第三列相当于在2号位
                  add dl,dl       ;字符是两个字节组成
                  mov bl,dl       
                  mov bh,0
                  mov di,bx       ;转化为字节的列数
                  
                  sub dh,1        ;第8行相当于7号位行
                  mov al,dh
                  mov ah,0
                  mov bx,00a0h    ;一行有160个字节
                  mul bx          ;找到字节位置
                  sub ax,1        ;减1得字属性位置
                  mov bp,ax       
                  
        s:          mov cx,[si]     ;判断字符串末尾
                  jcxz offset ok  ;cx为零停止
              mov cl,2        ;字符绿色属性
                  mov al,[si]     
                  mov es:[bp+di+1],al    ;将字属性放入显存
                  mov es:[bp+di+2],cl    ;将颜色属性放入字属性后一位
                  
                  add di,2               ;显存一个字符的单位
                  add si,1               ;数据段一个字符单位
                  
                  jmp short s
        ok:   ret                    ;提取字符串到末尾返回
code ends
end start

2.
assume cs:code


data segment
   dd 0,0
data ends

code segment
start: mov ax,data
           mov ds,ax
       
           mov ax,4240h
           mov dx,000fh
           mov cx,0ah
           
           call divdw
           mov ax,4c00h
           int 21h
           
           
divdw:mov bx,ax       
          mov ax,dx
          mov dx,bx               ;互换高低位
          mov si,0
          
          mov [si+4],dx           ;将dx = 4240h暂存数据空间   00 00 00 00 42 40 00 00 
      div cl                  ;八位除数
      mov bl,al               
      mov bh,0
          mov [si],bx             ;将高16位的商存数据空间      01 00 00 00 42 40 00 00
          
          mov dl,ah               ;余数存dx用于下一步16位除法  放入高16位相当于*65536
          mov dh,0
          
          mov ax,[si+4]           ;将原公式低16被除数放入ax准备运算16除法
          div cx                  ;运算后得到的ax既为结果低16位的商 86A0
          mov cx,dx               ;dx为最终余数
          mov word ptr dx,[si]    ;将数据空间内原本存储的高16位的商结合即为  186A0
          ret

code ends
end start


3.
assume cs:code

data segment
        dw 123,12666,1,8,3,38
data ends

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

stack segment
        dw 2 dup(0)                 ;暂存计数器
stack ends

code segment
start: mov ax,data              
           mov ds,ax
           
           mov ax,0b800h            ;存显存段地址
           mov es,ax
           
           mov ax,stack             
           mov ss,ax
           mov sp,4
           
           mov si,0
           mov di,0

           mov cx,6                 ;6个字符运行六次
     s:push cx
                                                                ;避免cx被干扰
           mov bx,0                 ;dtoc中 bx作为计数器为short计算位置
           mov bp,0                 ;bp为d断寻址偏移
           call dtoc
           
           add si,2                 ;dtoc中 si为data段中数值的偏移
           mov bp,0                 ;show_str中  bp同样作为对d段暂存字符串字属性的使用
           mov cx,bx                ;将dtoc得到的bx计数器作为show_str的循环次数,这样就知道要显示的数值到底是几位数
           call show_str        
           pop cx                   ;归还总体循环次数
           loop s
           
           mov ax,4c00h
           int 21h
         
dtoc:  mov ax,[si]
       mov cx,10
       mov dx,0
       div cx                    
       mov [si],ax
       add dx,30h                ;当前dx为余数,即为数值最后一位的数字    +30h为对应的ascii码
       mov ds:[bp+16],dl         ;倒序存入d段
       dec bp
       
       inc bx                    ;计数器为show_str使用
       mov cx,ax
       jcxz short ok             ;字符末尾返回
       jmp short dtoc
       
ok:    ret
       
       
show_str: mov ax,5               ;d段为五个字节
                  sub ax,cx              ;减去dtoc得到的计数器就可得知d段中有几个字属性,从哪个字节开始将数据传入显存
                  mov bp,ax              
                  mov al,ds:[bp+12]      
                  mov ah,2
          mov es:[di+1830],ax    ;1830为屏幕显示位置
          add di,2
          loop show_str
          add di,2               ;空格隔开
          ret

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

使用道具 举报

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

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

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

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

修正后的代码如下:
assume cs:code
data segment
    db 'Welcome to masm!',0
data ends

code segment
start:
    mov ax, data
    mov ds, ax
    mov dh, 8
    mov dl, 3
    mov si, offset data        ; si 初始化为字符串的起始地址
    call show_str
    
    mov ax, 4C00h
    int 21h

show_str:
    mov ax, 0b800h            ; 显存地址
    mov es, ax
    sub dh, 1                 ; 转化为实际行(显示从第7行开始)
    sub dl, 1                 ; 转化为实际列(显示从第2列开始)
    shl dl, 1                 ; 每个字符占两个字节
    mov di, dx                ; di = dh * 160 + dl*2
    shl dh, 7
    shl dh, 1
    add di, dh
    
    mov cx, 16                ; 假设字符串长度为16,包括结束符
s: 
    mov al, ds:[si]
    cmp al, 0                 ; 检测字符串结尾
    je ok
    mov es:[di], al
    mov es:[di + 1], 2        ; 设置颜色为绿色
    add di, 2
    inc si
    loop s
ok: 
    ret
code ends
end start

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

我们来修复并完成这部分代码:
assume cs:code
data segment
   result dd 0
data ends

code segment
start:
    mov ax, data
    mov ds, ax

    mov ax, 4240h
    mov dx, 0000h
    push dx                  ; 模拟 4240h 在高位
    push ax                  ; 模拟 0000h 在低位
    pop ax
    pop dx

    mov cx, 0Ah              ; 除数
    call divdw
    
    mov ax, 4C00h
    int 21h
       
divdw:
    mov ebx, edx: eax        ; 将 ax 和 dx 组合成 32 位(edx: eax)
    xor edx, edx
    div cx                   ; 执行 32 位除法,quotient 在 eax, remainder 在 edx
    mov ds: result, eax      ; 存储结果
    ret

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

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

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-22 09:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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