效果如图:
assume cs:code
parameters_stack segment ;程序断点参数传递
db 48 dup(0)
parameters_stack ends
raw_stack segment ;程序断点保存
db 48 dup(0)
raw_stack ends
alpha segment
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ;0~25
db 'abcdefghijklmnopqrstuvwxyz' ;26~51
db 'HI, WELCOME TO MASM! ' ;52~77
db 'I AM Cncdre FROM CHINA. ' ;78~103
db 'HOW ARE YOU? ' ;104~129
alpha ends
code segment
Main:
;参数传递
mov ax,parameters_stack
mov ss,ax
mov sp,32
mov ax,26
push ax ;字符串长度
mov ax,200h
push ax ;高地址为字符属性,低地址为0
mov ax,52
push ax ;待显示字符所在偏移地址
mov ax,alpha
push ax ;待显示字符所在段
mov ax,2000
push ax ;显存偏移地址
mov ax,0b800h
push ax ;显存起始段地址
mov ss:[1],sp ;parameters_stack最高地址存储此时栈顶位置
;断点保存
mov ax,raw_stack ;call指令会自动压入程序断点地址(ip,短转移)
mov ss,ax
mov sp,32
call Sub0
mov ax,4c00h
int 21h
Sub0:;小程序0_字符打印
;参数压栈顺序:
;字符串长度->高地址为字符属性,低地址为0->待显示字符所在偏移地址
;->待显示字符所在段->显存偏移地址->显存起始段地址
;最后在ss:[1]存入sp
push ax
push es
push di
push ds
push si
push cx
mov ss:[1],sp ;raw_stack最高地址存储此时栈顶位置
mov ax,parameters_stack
mov ss,ax
mov sp,ss:[1] ;parameters_stack最高地址读取栈顶位置
pop ax
mov es,ax ;显存起始段地址
pop di ;显存偏移地址
pop ds ;待显示字符所在段
pop si ;待显示字符所在偏移地址
pop ax ;低地址为0,高地址为字符属性
pop cx ;字符串长度
s:
mov al,ds:[bx+si]
mov es:[di],al
mov es:[di+1],ah
inc si
inc di
inc di
loop s
mov ax,raw_stack
mov ss,ax
mov sp,ss:[1] ;raw_stack最高地址读取栈顶位置
pop cx
pop si
pop ds
pop di
pop es
pop ax
ret ;ret指令会自动弹出程序断点地址赋给ip(短转移)
code ends
end Main