6YKT6ZKm5LqI 发表于 2022-6-29 17:39:50

实验九


这是调试的样子呜呜{:5_99:}
而且,显示字符串以后dosbox就会卡住,没法再输入指令{:10_243:}
代码如下:
assume cs: codesg, ds: data, ss: stack

data segment
    db 'welcome to masm!' ; 在显存显示的字符串(16个字符,需要占32个字节,一个字节存放asc码,一个字节存放字符属性)
    db 02h, 24h, 71h ; 定义三种颜色属性(黑底绿字, 绿底红字, 白底蓝字)
data ends

stack segment
    dw 8 dup(0) ; 定义8个字型数据用于存放寄存器的值
stack ends

codesg segment
start:
    mov ax, data
    mov ds, ax
    mov ax, stack
    mov ss, ax
    mov sp, 10h ; 设置栈顶,八个字型数据占16个字节,故偏移地址取10h

    xor bx, bx ; bx清零, 用来索引属性
    mov ax, 0b872h ; 定位第十二行中间位置(作段地址使用): (11 * 160 + (80 - 16) / 2 * 2)在转换为16进制

    mov cx, 3 ; 执行三次循环,打印三行语句
s3:
    push cx ; 为外循环保存相关寄存器的值
    push ax ; 防止段地址的值在内循环中被改变
    push bx

    mov es, ax ; 此时es为显存的段地址

    mov si, 0 ; si用于索引字符
    mov di, 0 ; di用于定位字符存往的es段的偏移地址

    mov cx, 10h
    ; s1控制存放的字符,内循环为10h次,因为一行含10h个字节(注意!十六进制的10表示十进制的16)
s1:
    mov al, ds:
    mov es:, al
    inc si
    add di, 2
    loop s1
    ; 将字符存入偶数偏移地址

    mov di, 1
    pop bx
    mov al, ds:10h ; 取出字符串属性赋给al
    inc bx ; ds:指向下一行字符串的属性

    mov cx, 10h
s2:
    mov es:, al
    add di, 2
    loop s2
    ; 存入字符属性

    pop ax
    add ax, 00A0H ; 将段地址修改到下一行
    loop s3

    mov ax, 4c00h
    int 21h
codesg ends
end start

人造人 发表于 2022-6-29 19:36:03

1. 在执行58行的 loop s3 之前,没有 pop cx
2. 27行的 push bx 和45行的 pop bx 之间修改过bx寄存器吗?为什么要保存bx ?
3. 代码成对编写就不会出现这样的问题
    mov cx, 10h
    mov cx, 10h
s3:
    loop s3
    mov cx, 10h
s3:
    push cx
    pop cx
    loop s3

    mov cx, 10h
s3:
    push cx

    push ax
    pop ax

    pop cx
    loop s3

像这样,一对一对的写,这样就不会漏掉 pop cx 了

人造人 发表于 2022-6-29 19:37:47

    mov cx, 10h
s3:
    push cx

    push ax

    ; 其他代码继续在这里写

    pop ax

    pop cx
    loop s3

6YKT6ZKm5LqI 发表于 2022-6-29 23:30:28

人造人 发表于 2022-6-29 19:37


我改了一下,但是还是只能打印出一行,而且打印出来的是"Aelcome to masm!", 第一个字符有问题,可以麻烦再帮我看一下是哪里有问题吗{:10_266:}

assume cs: codesg, ds: data, ss: stack

data segment
    db 'welcome to masm!' ; 在显存显示的字符串(16个字符,需要占32个字节,一个字节存放asc码,一个字节存放字符属性)
    db 02h, 24h, 71h ; 定义三种颜色属性(黑底绿字, 绿底红字, 白底蓝字)
data ends

stack segment
    dw 8 dup(0) ; 定义8个字型数据用于存放寄存器的值
stack ends

codesg segment
start:
    mov ax, data
    mov ds, ax
    mov ax, stack
    mov ss, ax
    mov sp, 10h ; 设置栈顶,八个字型数据占16个字节,故偏移地址取10h

    xor bx, bx ; bx清零, 用来索引属性
    mov ax, 0b872h ; 定位第十二行中间位置(作段地址使用): (11 * 160 + (80 - 16) / 2 * 2)在转换为16进制

    mov cx, 3 ; 执行三次循环,打印三行语句
s3:
    push cx ; 为外循环保存相关寄存器的值
    push ax ; 防止段地址的值在内循环中被改变
    ; push bx

    mov es, ax ; 此时es为显存的段地址

    mov si, 0 ; si用于索引字符
    mov di, 0 ; di用于定位字符存往的es段的偏移地址

    mov cx, 10h
    ; s1控制存放的字符,内循环为10h次,因为一行含10h个字节(注意!十六进制的10表示十进制的16)
s1:
    mov al, ds:
    mov es:, al
    inc si
    add di, 2
    loop s1
    ; 将字符存入偶数偏移地址

    mov di, 1
    ; pop bx
    mov al, ds:10h ; 取出字符串属性赋给al
    inc bx ; ds:指向下一行字符串的属性

    mov cx, 10h
s2:
    mov es:, al
    add di, 2
    loop s2
    ; 存入字符属性

    pop ax
    pop cx
    add ax, 00A0H ; 将段地址修改到下一行
    loop s3

    mov ax, 4c00h
    int 21h
codesg ends
end start

jackz007 发表于 2022-6-29 23:57:04

本帖最后由 jackz007 于 2022-6-30 00:22 编辑

assume cs: code , ds: data

data segment para public 'data'
      db 'welcome to masm!'
      db 02h , 24h , 71h   
data ends

stack segment para stack 'stack'       ; 这样定义,编译器能够识别出堆栈段,并自动对号入座 ss 和 sp,不必专门用代码进行初始化。
      dw 800h dup(0)               ; 必须定义足够大的堆栈空间,否则,如果堆栈空间不够使用,程序将无法正常运行,甚至可能直接奔溃。
stack ends

code segment para public 'code'
start:mov ax, data
      mov ds, ax
      mov ax,0b800h
      mov es,ax
      mov di,726h
      xor bx,bx
      mov cx,3
      cld
s1:   push cx
      xor si,si
      mov cx,10h
s2:   movsb
      mov al,
      stosb
      loop s2
      inc bx
      pop cx
      add di,128
      loop s1
      xor ax,ax
      int 16h
      mov ax,4c00h
      int 21h
code ends
end start

人造人 发表于 2022-6-30 01:01:00

6YKT6ZKm5LqI 发表于 2022-6-29 23:30
我改了一下,但是还是只能打印出一行,而且打印出来的是"Aelcome to masm!", 第一个字符有问题,可以麻烦 ...

    add ax, 00A0H ; 将段地址修改到下一行
下一行是加 a0 吗?
下一行应该加多少?


试试这个
add ax, 0AH

人造人 发表于 2022-6-30 01:09:40

6YKT6ZKm5LqI 发表于 2022-6-29 23:30
我改了一下,但是还是只能打印出一行,而且打印出来的是"Aelcome to masm!", 第一个字符有问题,可以麻烦 ...

Aelcome to masm
不要忘了你用的debug程序调试的程序
debug程序也要写显存的,而且是你的程序先写,debug程序后写
你的程序先写了一个w,然后debug程序又写了一个A,正好覆盖了你的程序写的那个w
如果debug程序不写显存的话,你怎么能从屏幕上看到当前执行的哪条指令,当前寄存器中的值
debug程序把这些数据写到显存,然后你就从屏幕上看到了

nikezhi 发表于 2022-6-30 01:57:29

{:5_108:}

eyuyan 发表于 2022-6-30 01:57:46

{:7_146:}
页: [1]
查看完整版本: 实验九