鸡脖子 发表于 2024-9-10 16:18:28

实验十



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,   ;判断字符串末尾
                  jcxz offset ok;cx为零停止
              mov cl,2      ;字符绿色属性
                  mov al,   
                  mov es:,al    ;将字属性放入显存
                  mov es:,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 ,dx         ;将dx = 4240h暂存数据空间   00 00 00 00 42 40 00 00
      div cl                  ;八位除数
      mov bl,al               
      mov bh,0
          mov ,bx             ;将高16位的商存数据空间      01 00 00 00 42 40 00 00
          
          mov dl,ah               ;余数存dx用于下一步16位除法放入高16位相当于*65536
          mov dh,0
          
          mov ax,         ;将原公式低16被除数放入ax准备运算16除法
          div cx                  ;运算后得到的ax既为结果低16位的商 86A0
          mov cx,dx               ;dx为最终余数
          mov word ptr dx,    ;将数据空间内原本存储的高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,
       mov cx,10
       mov dx,0
       div cx                  
       mov ,ax
       add dx,30h                ;当前dx为余数,即为数值最后一位的数字    +30h为对应的ascii码
       mov ds:,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:      
                  mov ah,2
          mov es:,ax    ;1830为屏幕显示位置
          add di,2
          loop show_str
          add di,2               ;空格隔开
          ret

code ends
end start
                  

FishC 发表于 2024-9-10 16:29:56

看起来你在求助于两个不同的汇编程序,分别是一个字符串显示程序和一个双字除法程序。让我来帮助你完成这些程序,并解决其中存在的问题。

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

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

1. `show_str` 子程序中缺少字符串长度的初始化。
2. 需要赋值 `es:` 处的显存地址。
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:
    cmp al, 0               ; 检测字符串结尾
    je ok
    mov es:, al
    mov es:, 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 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 实验十