Noseel

导航

实验3 转移指令跳转原理及其简单应用编程

 

实验任务1

task1.asm

assume cs:code, ds:data

data segment
    x db 1, 9, 3   ;db中b表byte,一个字节
    len1 equ $ - x ;符号常量,$表一个数据项的偏移地址,此处为3 

    y dw 1, 9, 3   ;dw中w表word,两个字节
    len2 equ $ - y ;符号常量,$表一个数据项的偏移地址,此处为9(3 + 6)
data ends

code segment
start:
    mov ax, data
    mov ds, ax        ;数据处理

    mov si, offset x  ;取符号x对应的偏移地址0 -> si
    mov cx, len1      ;从符号x开始的连续字节数据项个数
    mov ah, 2         ;ah==2时显示输出dl中的字符字段
 s1:mov dl, [si]      ;si表示x对应的偏移地址,将x的第一个数据移到dl中
    or dl, 30h        ;转化成ASCII码
    int 21h

    mov dl, ' '       ;输出空格
    int 21h

    inc si            ;移到下一个数据
    loop s1           ;继续执行s1

    mov ah, 2         ;显示输出dl中的字符字段
    mov dl, 0ah       ;0ah的ASCII值表示换行符:输出换行符
    int 21h

    mov si, offset y  ;将y的偏移量移到si中
    mov cx, len2/2    ;因为y的数据间隔是两个字节,数量就是字节总数/2
    mov ah, 2         ;显示输出dl
 s2:mov dx, [si]      ;之后操作同s1
    or dl, 30h
    int 21h

    mov dl, ' '
    int 21h

    add si, 2
    loop s2

    mov ah, 4ch
    int 21h
code ends
end start

实验结果

 

 

回答问题

0019-000d=000c=12 所以偏移量是12。cpu角度分析:读取loop s1指令进入指令缓冲器。根据读取指令的长度,修改IP的值,(IP)=(IP)+所读取指令的长度,从而指向下一条指令。执行loop 指令,跳转到s1处,s1处的偏移地址减去当前IP所指向的内存单元的偏移地址就是跳转后的偏移地址。

 

 

 

 

0037-0029=000e=14 所以偏移量是14。cpu角度分析:读取loop s2指令进入指令缓冲器。根据读取指令的长度,修改IP的值,(IP)=(IP)+所读取指令的长度,从而指向下一条指令。执行loop 指令,跳转到s2处,s2处的偏移地址减去当前IP所指向的内存单元的偏移地址就是跳转后的偏移地址。

 

 

在debug中进行调试观察的反汇编截图

实验任务2

task2.asm

assume cs:code, ds:data

data segment
    dw 200h, 0h, 230h, 0h
data ends

stack segment
    db 16 dup(0)
stack ends

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

    mov word ptr ds:[0], offset s1  ;word ptr表示这是一个字,将s1的偏移地址移入ds:[0](ds:[1])中
    mov word ptr ds:[2], offset s2
    mov ds:[4], cs                  ;cs表段地址,移到ds:[4]中(ds:[5])

    mov ax, stack
    mov ss, ax                      ;将栈的段地址移入ss中
    mov sp, 16                      ;预留16字节的栈空间

    call word ptr ds:[0]            ;call指令+word ptr作用:将下一个指令偏移地址入栈,跳转到ds:[0]
s1: pop ax                          ;将栈顶出栈到ax

    call dword ptr ds:[2]           ;call+dword ptr作用:将下一指令段地址、偏移地址依次入栈,跳转到ds:[2]
s2: pop bx
    pop cx

    mov ah, 4ch                     ;ah==4ch作用为带返回值al结束
    int 21h                         ;进入中断程序
code ends
end start

实验结果

 

 Line31的偏移地址为0028

回答问题

①根据call指令的跳转原理,先从理论上分析,程序执行到退出(line31)之前,寄存器(ax) = 0021h 寄存器(bx) = 0026h 寄存器(cx) = 076ch

② 对源程序进行汇编、链接,得到可执行程序task2.exe。以下为反汇编截图
 

实验任务3

task3.asm

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

data segment
    x db 99, 72, 85, 63, 89, 97, 55
    len equ $ - x ;$表偏移量 此处为7
data ends

stack segment
    dw 16 dup(0) ;定义一个容量为16字节的栈段 初始量为0
stack ends

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

    mov ax, stack
    mov ss, ax
    mov sp, 32

    mov cx, len ;数据部分为db,所以len为数据个数(7)
    print: ;打印数字
        mov ah, 0                 ;数据只有一个字节,把ah置0,以ax作为被除数
        mov al, byte ptr ds:[di]    ;把数据放入al
        inc di                    ;di指针后移

        push cx             ;把cx保存起来,

        call printNumber    ;打印数字
        call printSpace     ;打印空格

        pop cx              ;弹出cx
    loop print

    mov ah, 4ch             ;ah==4ch作用为带返回值al结束
    int 21h                 ;进入中断程序

;子程序: printNumber 功能: 打印数字
;入口参数:
;寄存器ax  (待输出的数据 --> ax)
;局部变量说明:
;bx -> 存储数字字符个数
printNumber:
    mov bx, 0       ;获取之前位数为0 逐位获取数字
    ; getNumber获取每一位压入栈中
    getNumber:
        mov dl, 10
        div dl          ;数据除10

        push ax         ;将数字压入栈中(ah余数在ax里)
        inc bx          ;位数+1

        mov ah, 0       ;ah是余数,置0后ax表示除法的结果
        mov cx, ax      ;除法结果赋给cx, 如果结果为0则说明所有位数都获取完了
        inc cx          ;防止出现负数

    loop getNumber

    ; 打印数字
    mov cx, bx          ;把bx存的数字位数赋给cx
    ; printNumberr依次从栈中取出数字,逐位进行打印
    printNumberr:
        pop ax          ; 取出一位数
        add ah, 30h     ; ah是除法的余数,即需要得到的位数,+30h是转成对应字符
        mov dl, ah      ; 放到dl, 用于打印
        mov ah, 2       ; 调用int 21h的2号子程序打印:显示输出dl
        int 21h
    loop printNumberr

    ret

;printSpace打印空格
printSpace:
    mov ah, 2
    mov dl, 20h
    int 21h
    ret
code ends
end start

实验结果

实验任务4

task4.asm

assume cs:code, ds:data
data segment
    str db 'try', 0
data ends

code segment
start:
    mov ax, data
    mov ds, ax
    mov si, offset str ;将str的偏移量移到si中
    mov al, 2
    call printStr
    mov ah, 4ch
    int 21h
;功能:在指定行、以指定颜色,在屏幕上显示字符串
;入口参数
;字符串首字符地址 --> ds:si(其中,字符串所在段的段地址—> ds, 字符串起始地址的偏移地址—> si)
;字符串长度 --> cx
;字符串颜色 --> bl
;指定行 --> bh (取值:0 ~24)
printStr:
    push bx
    push cx
    push si
    push di
    mov bx, 0b800H
    mov es, bx
    mov di, 0
s:  mov cl, [si]
    mov ch, 0
    jcxz qaq
    mov ch, al
    mov es:[di], cx
    inc si
    add di, 2
    jmp s
qaq:pop di
    pop si
    pop cx
    pop bx
    ret

code ends
end start

实验结果

实验任务5

task5.asm

assume cs:code, ds:data

data segment
    stu_no db '201983290213'
    len = $ - stu_no
data ends

code segment
start:
    mov ax, data
    mov ds, ax
    mov di, 0           ;数据处理

    call printStuNum    ;调用打印子程序

    mov ah, 4ch         ;21h的4ch子程序:带返回码al结束
    int 21h

;打印子程序:
;参数说明:
;学号字符串存储在 -> ds:[di]
printStuNum:
    mov ax, 0b800h
    mov es, ax      ;控制显存区域段指针
    mov si, 1       ;显存区域列指针

;把屏幕前24行背景打印成蓝色
    mov al, 24      ;前24行
    mov dl, 80      ;每行80个字符需要修改颜色
    mul dl          ;24*80, 获得需要填充蓝色的字符数

    mov cx, ax
    Blue:
        mov al, 17h         ;蓝底+白字:0 001 0 111 -> 17h
        mov es:[si], al     ;把颜色填充到位
        add si, 2           ;后移2个
    loop Blue

    sub si, 1        ;指针回退一个, 从最后一行起始位置开始

;打印最后一行
    mov ax, 80
    sub ax, len      ;80列 - 学号长度
    mov dl, 2
    div dl           ;(80 - len)/2, 学号左右两侧需要填充'-'的长度
    mov dx, ax       ;dx保存'-'的长度

    ;调用打印'-'的子程序, 打印左侧的'-'
    mov cx, dx
    call printgang

    ;打印学号
    mov cx, len
    printNumber:
        mov al, ds:[di]        ;低位是字符
        mov ah, 17h                ;高位是颜色
        mov word ptr es:[si], ax    ;按字放入
        inc di
        add si, 2
    loop printNumber

    ;调用打印'-'的子程序, 打印右侧'-'
    mov cx, dx
    call printgang
    ret
;子程序: 打印分隔符'-'
;参数: 长度 -> cx
;位置 -> es:[si]
printgang:
    mov al, '-'
    mov ah, 17h
    mov word ptr es:[si], ax
    add si, 2
    loop printgang
    ret

code ends
end start

实验结果

 

 

posted on 2021-11-30 14:07  Noseel  阅读(16)  评论(1编辑  收藏  举报