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
代码:
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
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
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
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
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步
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
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