汇编小问题 一个程序要求编制一个程序把BX寄存器内的二进制数用十六进制数的形式在屏幕上显示出来

我的问题是 这段程序中用了 PUSH DS
SUB AX,AX
PUSH AX
请问为什么要用这段框架结构  什么时候用这个 我知道这个是INT 20H指令 我就是不会用 不知道什么进用这个  求高手给我讲一讲

这个方式,是在DOS 2.0之前,还没有出现4CH号功能调用之前所用的方式。

那时候,退出DOS程序,用的是 INT 20H 号中断。
但这个中断能正确执行的前提,是CS必须是程序加载时的PSP前缀的段地址。
这对.com格式的程序,没有问题。它加载后CS就是PSP所在的段。
对.exe格式的文件,加载时CS被指向了程序入口代码的段地址,直接用 INT 20H就不对了。

为了解决EXE格式的程序正确返回DOS的问题,就产生了你提到的这种程序框架。
首先,要知道两点预备知识:
1. EXE程序加载时,DS是指向PSP前缀的。
2. PSP前缀总长100H个字节,它最前面偏移地址为0处的第一条代码正是 INT 20H

框架是这样的:

MAIN PROC FAR ;这里必须将过程属性定义成远调用,是为了保证最后的RET是远返回
PUSH DS ; 这里入栈的DS,就是PSP的段地址
SUB AX, AX ;
PUSH AX ; 这里入栈的 0 用来作为指向PSP第一条指令 INT 20H的偏移地址使用

; (这里是程序主体)

RET ; 由于段属性是FAR,所以这个返回是远返回。
; 远返回,是从栈中弹出两个字,送IP和CS。
; 因此,这就是将第一条指令的那个DS送CS,保证了CS指向程序加载时PSP
; 而从栈中弹出送入 IP 的就是上面入栈的那个0
;这样,RET 指令执行后,下一条指令 就是 PSP 头部的那条 INT 20H,且CS正确。

MAIN ENDP

这里,我没有写出段定义部分,以及ASSUME等。
最后,END 伪操作后面跟MAIN,将MAIN 指定为程序的入口。

顺便说一下,这种框架,是早就应当被淘汰的。
有了4CH号DOS系统功能调用以后,根本就不应该再使用这种繁琐、易出错的框架。
只是,编写教材的人,全是一些抄袭成性、不负责的懒东西。 第一个人抄原始的手册,第二个人抄第一个人的,第三个人抄第二人人的……结果,直到现在,我们还能在某些书上看到这种已成为垃圾的原始代码。

`追问

麻烦问一下 如果不用这段话应该怎么写 在哪里写MOV AH ,4CH
INT 21H

追答

MOV AH,4CH
INT 21H

这两条指令执行后,程序就结束运行了。它自然是写在需要结束程序的地方,在主程序的最后,作为主程序的结束。

由于完整程序中可能还有子程序定义等内容放在主程序的后面,因此,这两条指令不一定是在整个程序代码的最后位置, 不一定是在END 伪指令的前面。

温馨提示:内容为网友见解,仅供参考
无其他回答

汇编小问题 一个程序要求编制一个程序把BX寄存器内的二进制数用十六进制...
1. EXE程序加载时,DS是指向PSP前缀的。2. PSP前缀总长100H个字节,它最前面偏移地址为0处的第一条代码正是 INT 20H 框架是这样的:MAIN PROC FAR ;这里必须将过程属性定义成远调用,是为了保证最后的RET是远返回 PUSH DS ; 这里入栈的DS,就是PSP的段地址 SUB AX, AX ;PUSH ...

...在BX寄存器内的值(二进制数)用十六进制数的形式在屏幕上显示出来...
MOV CH,4 ;循环四次 LOP: MOV CL,4 ROL BX,CL ;每次循环环左移四位 MOV DX,BX AND DL,0FH ;每次取低四位,来表示一个十六进数 ADD DL,30H ;转化成为ASSIC码 CMP DL,3AH ;判断DL是否大于10的ASSIC码(A+30H)JB NEXT ADD DL,7 ;大于10再加上7 NEXT: MOV AH...

汇编语言:编写一个程序,显示AL寄存器中的两位十六进制数
;disp_al子程序将寄存器AL中的数值以十六进制显示出来disp_al: mov dh, al mov bx, 2 ;bx用于循环,一个字节最多可以显示成两个字符,所以循环次数是2次 mov cl, 4 ;首先显示高4位,在下次循环进再显示低4位 shr al, clagain: and al, 0fh cmp al, 9 ja hex add al, '0' ;如果小于9,加上字符...

...AX中二进制“1”的个数,结果一位十六进制数的形式显示
code segment assume cs:code start:mov ax,1234 mov bl,0;统计1的个数 mov cx,16;循环次数 loop1:test ax,8000h;不断的左移,与8000h比较获取1的个数 jnz loop2 inc bl shl ax,1 loop2:loop loop1 ;输出1的个数 mov dl,bl add dl,30h mov ah,02h int 21h mov ah,4ch int 21h...

试编写一段程序将BX寄存器中的二进制数转变为八进制数,并在屏幕上显示...
MOV CL,1 ROL BX,CL PUSH BX AND BX,1 CALL DISP POP BX MOV DX,5 AG:MOV CL,3 ROL BX,CL PUSH BX AND BX,07 CALL DISP POP BX DEC DX JNZ AG INT 3 DISP:PUSH BX PUSH CX PUSH DX MOV AL,BL ADD AL,'0'MOV AH,2 INT 21H POP DX POP CX POP BX RET ...

汇编:将AX寄存器中16位二进制数分成四组,每组四位,然后把这四组数分别...
;1.把ax寄存器内容分4组每组4位,然后把这4组数分别放在AL,BL,CL,DL中assume cs:code code segment start: mov ax,1234h mov bx,ax mov cx,ax mov dx,ax and al,0fh ;al中是4 mov cl,4 shr bl,cl ;bl中是3 and ch,0fh ;ch中是2,先存在这,最后再给cl mov cl,4 shr dh,cl mov dl,dh ...

...编写一个程序,将AL寄存器中的一位十六进制数转化成ASCII码 显示输出...
;将AL寄存器中的一位十六进制数转化成ASCII码,显示输出。;推荐答案,写的并非是一位。;程序如下:ASSUME CS:CODE CODE SEGMENT START:MOV AL, 0FH ;在这里可写 00H~0FH,这就是一位16进制数 AND AL, 0FH ;无用位清零,保留该数字 ;下面是变成ASCII码 CMP AL, 0AH JB NEXT ADD...

跪求汇编语语言命令详解
u (Unassemble) 反汇编 u [address ]或range w (Write) 存盘 w [address[driver sector secnum> ? 联机帮助 ? debug小汇编a命令 debug小汇编a命令是一个很有用的功能,许多的小程序都要他来做。 编一些小程序比汇编要来得方便,快洁。 在Debug中,中断是非常有用的,首先,让我们先了解一下中断。 所谓...

怎么用汇编语言将数字组成的字符串转换成数值
MOV AX,1 d2: PUSH AX (将AX压栈,保护AX中的值)SUB BYTE PTR [SI],DL (由于字符是ASCII码表示的,因此减去30H后即可转换为十六进制数)MUL BYTE PTR [SI]ADD w,AX (year是前面定义的用来保存数值的字型量。即w DW 0)POP AX (上一步将数值保存到w中...

汇编语言程序设计题
sub al,7 ;使低4位等于对应字母的十六进制值@@Convert_Bin: and al,0fh ;转换成二进制数 push ax ;入栈保存 loop @@Input_Hex ;接受下一个数字@@Return_Hex: mov ax,cx mov cx,cs:@@Hexadec sub cx,ax jcxz @@Return_pop std@Reverse_Order:pop ax stosb ;保存 loop @Reverse_Order@@Return_po...

相似回答