汇编学习--第九天

实验9 根据材料编程

注意:

在做第十章课后题时,发现个问题,最上面红框和下面两个红框,对偏移地址000h的叫法不同,我根据实际显示,es:000h叫0行0列(这一行不会在显示器上显示)

assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
    db 'welcome to masm!'
    db 02h,24h,71h;三种颜色
datasg ends
stacksg segment
    db 16 dup (0)
stacksg ends
codesg segment
        ;datasg段地址
start:    mov ax,datasg
        mov ds,ax
    
        ;stacksg段地址
        mov ax, stacksg
        mov ss,ax
        mov sp,10h
        
        ;目标地址
        mov ax,0b800h
        mov es,ax
        
        mov cx,3
        mov di,10h;在datasg中的偏移量
        mov bx,780h;表示第12行
        ;第一层循环,3种颜色
s:        mov si,0;在显示缓冲区中的偏移地址
        mov ah,ds:[di]
        push cx
        push di
        
        mov di,0
        mov cx,16
        ;第二层循环,字符串
s0:        mov al,ds:[di]
        mov es:[bx+si+64],al;低位存字符
        mov es:[bx+si+64+1],ah;高位存属性
        inc di
        add si,2
        loop s0
        
        pop di
        pop cx
        inc di
        add bx,0a0h
        loop s
        
        mov ax,4c00h
        int 21h
codesg ends
end start

要理解材料中的几个点:

  • 1.每行可以表示80个字符,160字节
  • 2.每行的偏移地址规律----起始偏移地址:行数  * 160    结束偏移地址:起始地址+159  (这里都是十进制表示,需要转换为十六进制)
  • 3.属性字节格式,一共8位,每四位对应十六进制的字节的高位和低位。1表示有这个属性,0表示没有。

概括

这道题简单的说就是将字符数据属性数据写入b800h(显示缓冲区),并居中显示。

分步解析

  • 1.要居中,首先行居中为12行开始,根据上面的公式得到起始偏移地址780h,而下一行起始地址就是 原偏移地址+0a0h--0a0h为160字节;
  • 2.列居中,字符串占16字符,总共80字符,还剩64字符,也就是128字节,字符串前后等距,为128/2=64字节,所以需要在偏移地址基础上加64
  • 2.从自定义的datasg段中取字符串和属性数据,字符串写入低位:0b800h:[起始偏移地址+64]   属性写入高位:0b800h:[起始偏移地址+1+64]

第十章 CALL和RET指令

10.1 ret和retf

ret指令:使用栈中数据修改IP,实现近转移

retf指令:使用栈中数据修改CS和IP,实现远转移

执行ret相当于是pop IP,将栈顶元素作为IP值

执行retf相当于pop IP,pop CS,和ret类似

ret的应用

assume cs:codesg,ss:stacksg
stacksg segment
    db 16 dup (0)
stacksg ends
codesg segment
        mov ax,4c00h
        int 21h
    
start:    mov ax,stacksg
        mov ss,ax
        mov sp,10h
        mov ax,0
        push ax
        ret
codesg ends
end start

retf应用

assume cs:codesg,ss:stacksg
stacksg segment
    db 16 dup (0)
stacksg ends
codesg segment
        mov ax,4c00h
        int 21h
    
start:    mov ax,stacksg
        mov ss,ax
        mov sp,10h
        mov ax,0
        push cs
        push ax
        retf
codesg ends
end start

检测点 10.1

assume cs:codesg
stacksg segment
    db 16 dup (0)
stacksg ends
codesg segment
start:    mov ax,stacksg
        mov ss,ax
        mov sp,10h
        mov ax,1000h
        push ax
        mov ax,0
        push ax
        retf
codesg ends
end start

10.2 call指令

使用call指令进行两步:

  • 1.将IP或CS和IP压入栈中
  • 2.转移

call实现转移方法和jmp相似

10.3 依据位移进行转移的call指令

call + 标号

相当于执行

push ip

jmp near ptr 标号

检测点 10.2

ax=6

在读入指令call s时,IP首先自动+3(下一个指令偏移地址),所以入栈的数据为6,pop ax也就是ax=6

assume cs:codesg
codesg segment
start:    mov ax,0
        call s
        inc ax
s:        pop ax
        
        mov ax,4c00h
        int 21h
codesg ends
end start

10.4 转移的目的地址在指令中的call指令

call far ptr 标号

相当于执行

push CS

push IP

jmp far ptr 标号

检测点 10.3

assume cs:codesg
codesg segment
        mov ax,4c00h
        int 21h
        
start:    mov ax,0
        call far ptr s;入栈的IP为8,CS为1000h
        inc ax
s:        pop ax;ax=8
        add ax,ax;ax=16
        pop bx;bx=1000h
        add ax,bx;ax=1010h
        
        mov bx,0
        push bx
        ret
codesg ends
end start

因为在我的代码中,入栈CS=076AH,IP=DH

所以

assume cs:codesg
codesg segment
        mov ax,4c00h
        int 21h
        
start:    mov ax,0
        call far ptr s;入栈的IP为dh,CS为076ah
        inc ax
s:        pop ax;ax=dh
        add ax,ax;ax=1ah
        pop bx;bx=076ah
        add ax,bx;ax=0784h
        
        mov bx,0
        push bx
        ret
codesg ends
end start
原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11167474.html