王爽汇编 (十)实验

检测点 10.1
assume cs:code
stack segment
	db 16 dup (0)
stack ends
code segment
start:
	mov ax,stack
	mov ss,ax
	mov sp,16
	mov ax,1000h;______
	push ax
	mov ax,0h;_____
	push ax
	retf
code ends
end start		

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

callf 和 retf 示意图

代码:

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

分析如图:
在这里插入图片描述

检测点10.2 call

assume cs:codesg
codesg segment
start:
mov ax,0
call s 
inc ax ;上面call前会保存的是这条地址的 cs ip
s:
    pop ax
codesg ends
end start

在这里插入图片描述
在这里插入图片描述

call 只会 是近跳转 相当于
push ip
jmp newip

检测点10.3 call far

assume cs:codesg
codesg segment
start:
mov ax,0h
call far ptr s 
inc ax ;上面call前会保存的是这条地址的 cs ip
s:
    pop ax ;ax = 08 
    add ax,ax ;ax=10h
    pop bx	;bx=cs
    add ax,bx ;ax = cs + 10h
codesg ends
end start

在这里插入图片描述
在这里插入图片描述
call far
等价于
push cs
push ip
jmp far cs:ip

检测点10.4

assume cs:codesg
codesg segment
start:
mov ax,6
call ax
inc ax
mov bp,sp
add ax,[bp]
codesg ends
end start

在这里插入图片描述
ax =6
栈里存了返回 ip 为 5
所以 5 + 6 = 11 = B
在这里插入图片描述

检测点10.5

(1)
assume cs:code
stack segment
	dw 8 dup (0)
stack ends
code segment
  start:
	mov ax,stack
	mov ss,ax
	mov sp,16
	mov ds,ax
	mov ax,0
	call word ptr ds:[0EH]
	inc ax
	inc ax
	inc ax
	mov ax,4c00h
	int 21h
code ends
end start		

在这里插入图片描述

call 指令等价于 2步

  1. push ip
    ip =ss:[sp-2] =ss:[e] 所以ss:[e] 处 值为 11 00
  2. jmp targetip
    targetip = ds:[e]
    由于 ds = ss 所以 ds:[e] = ss:[e] = 11 00
    所以程序 JMP ip:0011 处 就跳转到了下一条指令
(2)
assume cs:code
data segment
	dw 8 dup (0)
data ends
code segment
  start:mov ax,data
  mov ss,ax
  mov sp,16
  mov word ptr ss:[0],offset s
  mov ss:[2],cs
  call dword ptr ss:[0]
s:mov ax,offset s
    sub ax,ss:[0cH]
    mov bx,cs
    sub bx,ss:[0eH]
    mov ax,4c00h
    int 21h
code ends
end start    

在这里插入图片描述
在这里插入图片描述
结果 ax 和 cx 为 0

实验十

1.按指定行号列号显示0结尾的字符串

assume cs:codesg ds:datasg ss:stacksg
datasg segment
db 'welcome to masm!',0;显示内容
datasg ends
codesg segment
start:
        mov dh,8;行数
        mov dl,3;列数
        mov cl,2;显示模式
        mov ax,datasg
        mov ds,ax;将数据段指向
        mov bx,0
        mov si,0
        call show_str
        mov ax,4c00h
        int 21h
show_str:
        mov ax,0b800h
        mov es,ax;指向显卡缓存开始
        mov al,0a0h ;第一行 160字节
        mul dh;结果放在ax
        mov dh,0
        add dl,dl;一列占2个字节
        add ax,dl;计算行列偏移
        mov bx,ax;写入的显卡缓存起始偏移
        mov al,cl;显示模式
    prtf:
        mov ah,[si];取出字节
        mov es:[bx + 0],ah;显示内容
        mov es:[bx + 1],al;显示模式
        add bx,2;写入显卡缓存偏移+2
        inc si;取出数据地址偏移+1
        mov cx,byte ptr[si];用来判断是否是 0结尾 若是0 就会跳出循环
        add cx,1
        loop prtf
        ret
codesg ends
end start

在这里插入图片描述

这样子 以后 想要显示字符穿内容 就可以直接调用 我们写的 方法了 只要设置段 数据寄存器 显示的行号 显示的列号 显示模式 就可以打出 指定字符。

2.写一个不会产生除法溢出的除法运算,被除数为dword类型,除数为word类型,结果为word类型。

在这里插入图片描述

assume cs:codesg ss:stacksg
stacksg segment
dw '0','0','0','0','0','0','0','0'
stacksg ends
codesg segment
start:
	mov ax,stacksg
	mov ss,ax
	mov sp,10h
	mov ax,04240h;L
	mov dx,000fh;H
	mov cx,0ah;n
	call divdw
	mov ax,4c00h
	int 21h
divdw:
	push ax
	mov ax,dx
	mov dx,0
	div cx;H/N
	mov bx,ax;保存商 作为最后 32位的前16位
	pop ax;//L 此时 余数在dx 相当于 dx:rem(H/M) ax:L  乘以 65536相当于 进位一个寄存器 所以rem(H/M)在 dx高位寄存器中
	div cx ;对 dx ax /N
	mov cx,dx ;将余数 赋值给cx
	mov dx,bx;将 
	ret
codesg ends
end start

最后返回和书提供的值一致。
在这里插入图片描述

将work型数据转变为表示十进制数的字符串,字符串以0结尾。

assume cs:codesg ds:datasg ss:stacksg
datasg segment
db  10 dup (0)
datasg ends
stacksg segment
dw '0','0','0','0','0','0','0','0'
stacksg ends
codesg segment
start:
        mov ax,stacksg
        mov ss,ax
        mov sp,10h
        mov dx,05ah;要显示的字符高16位
        mov ax,09768h;低16位
        mov bx,datasg
        mov ds,bx
        mov si,0
        call dtoc
        mov dh,8;行数
        mov dl,3;列数
        mov cl,2;显示模式
        mov ax,datasg
        mov ds,ax;将数据段指向
        mov bx,0
        mov si,0
        call show_str
        mov ax,4c00h
        int 21h
dtoc:
        mov cx,10
        call divdw
        add cx,030h;转ASCII码
        push cx
        inc si
        mov bx,0
        mov cx,ax
        add cx,dx
        jcxz ok
        jmp short dtoc;失败跳转循环
ok:
        pop ax
        mov byte ptr [bx],al
        inc bx
        sub si,1
        mov cx,si
        jcxz rtu
        jmp short ok
rtu:
        ret
divdw:
        push ax
        mov ax,dx
        mov dx,0
        div cx;H/N
        mov bx,ax;保存商 作为最后 32位的前16位
        pop ax;//L 此时 余数在dx 相当于 dx:rem(H/M) ax:L  乘以 65536相当于 进位>一个寄存器 所以rem(H/M)在 dx高位寄存器中
        div cx ;对 dx ax /N
        mov cx,dx ;将余数 赋值给cx
        mov dx,bx;将
        ret
show_str:
        mov ax,0b800h
        mov es,ax;指向显卡缓存开始
        mov al,0a0h ;第一行 160字节
        mul dh;结果放在ax
        mov dh,0
        add dl,dl;一列占2个字节
        add ax,dl;计算行列偏移
        mov bx,ax;写入的显卡缓存起始偏移
        mov al,cl;显示模式
    prtf:
        mov ah,[si];取出字节
        mov es:[bx + 0],ah;显示内容
        mov es:[bx + 1],al;显示模式
        add bx,2;写入显卡缓存偏移+2
        inc si;取出数据地址偏移+1
        mov cx,byte ptr[si];用来判断是否是 0结尾 若是0 就会跳出循环
        add cx,1
        loop prtf
        ret
codesg ends
end start

在这里插入图片描述
成功打印出字符。

发布了85 篇原创文章 · 获赞 5 · 访问量 4713

猜你喜欢

转载自blog.csdn.net/weixin_41315492/article/details/104232245