汇编程序返回dos的方法.高手请进.

a19861028 2007-11-05 09:50:48
我初学,不太清楚 这几种方法的异同,请高手灌水.
首先我开个头.

MOV AH 4CH;不能写成4c00h
INT 21H

该功能是指,终止当前程序的运行,并把控制权交给调用它的程序。由被终止程序打开的全部文件都被关闭,该项功能还把程序占用的内存空间交还给DOS另行分配。该项功能允许被终止的程序传送一个“返回码”给调用它的程序。假若被终止的程序是由DOS 命令调入的,那么返回码可以被DOS批处理命令中的“ IF ERRORLEVEL ”子命令识别。入口参数: AL=返回码(或者不设置)。出口参数: 无。
...全文
1757 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
gsy999 2012-05-05
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 的回复:]
引用 16 楼 的回复:
回复#2楼:
我想知道为什么要先将 ds:0000h 压栈,是因为psp的原因吗?

一开始ds是指向psp的,在psp:0000处放着int 20h(即终止程序的指令),这种终止程序的方式不是一个好办法。建议终止程序用以下指令:
mov ah,4ch
mov al,退出码
int 21h
[/Quote]
  CSDN也犯神经,第一次回帖不显示,第二次回帖全显示。
gsy999 2012-05-05
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 的回复:]
回复#2楼:
我想知道为什么要先将 ds:0000h 压栈,是因为psp的原因吗?
[/Quote]
一开始ds是指向psp的,在psp:0000处放着int 20h(即终止程序的指令),这种终止程序的方式不是一个好办法。建议终止程序用以下指令:
mov ah,4ch
mov al,退出码
int 21h
gsy999 2012-05-05
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 的回复:]
回复#2楼:
我想知道为什么要先将 ds:0000h 压栈,是因为psp的原因吗?
[/Quote]
psp:0000 中放着一个int 20h的指令(退出).
程序的一开始将ds压入栈(它此时是指向psp的),0压入栈,在程序执行到ret时,会将0赋给ip,将压栈的ds值赋给cs,这样就执行了一条int 20h指令.(建议用mov ah,4ch int 21h)
KevinGarnett 2012-05-04
  • 打赏
  • 举报
回复
回复#2楼:
我想知道为什么要先将 ds:0000h 压栈,是因为psp的原因吗?
KevinGarnett 2012-05-04
  • 打赏
  • 举报
回复
我想知道为什么
Joke_Olive 2007-11-10
  • 打赏
  • 举报
回复
回复 13楼 feathergirl:
你没说想要编这个程序做什么,我只能猜测。
你是不是想要不回显地输入字符,如果是感叹号就退出,否则就显示这个字符并换行?

如果是这样,程序中有这几个问题:


第一处是个结构错误:

MAIN PROC FAR
PUSH DS
XOR AX,AX
PUSH AX

……

RET
MAIN ENDP

最后的END语句写成:
END MAIN
即可。这样可以省去一个START:标号。


这是一个完整的结构,一点不能错漏。
你没有MAIN定义却用了PUSH ,XOR,PUSH开头,其中的PUSH DS你还错写成了PUSH DX
没有MAIN定义是不能用RET返回的。

在这里,你错得一塌糊涂。看起来,你根本没搞清楚程序标准结构有几种,怎么用才正确。

除了上面这个框架,另外还有两种框架。你的教科书上应该有。
要作为整体去使用框架。


第二处很有可能会出错:
CMP AL, 21H

JNZ NEXT之间,隔太远了。
其间不仅CALL了一段,还INT了一次。
尤其是INT指令,跳过去执行了一大段DOS内核代码,而DOS并没有声明返回时PSW不变。事实上,很多DOS系统功能是要修改标志位并用它返回信息的。
所以,我不知道当你JNZ时,CMP的结果还在不在,条件转移能不能保证正常。

第三处是多余指令
在换行子程序里,那三级PUSH,POP对你的程序来说无用,可以省去。

feathergirl 2007-11-10
  • 打赏
  • 举报
回复
DATA SEGMENT
MSG1 DB "please input the string,!",0dh,0ah, "$"



DATA ENDS


CODE SEGMENT
ASSUME DS:DATA,CS:CODE
START:
PUSH DX
XOR AX,AX
PUSH AX
MOV DX,DATA
MOV DS,DX




LEA DX,MSG1
MOV AH,09
INT 21H ;用p调试


NEXT:
MOV AH,07
INT 21H

CMP AL,21H
MOV DL,AL
MOV AH,02
INT 21H
CALL newline
JNZ NEXT

;MOV AH,0
;INT 21H
;MOV AH,4CH ;返回DOS
;INT 21H
ret

newline PROC NEAR ;回车换行
PUSH DS
PUSH DX
PUSH AX

MOV DL,0ah
MOV AH,02
INT 21h

MOV DL,0dh
MOV AH,02
INT 21h

POP AX
POP DX
POP DS
RET

newline ENDP

CODE ENDS
END START
feathergirl 2007-11-10
  • 打赏
  • 举报
回复
to 张三李四

"你上面的最后一个INT后面没中断号,当然是无效指令 "
我写了,只是没复制好.
a19861028 2007-11-06
  • 打赏
  • 举报
回复
不好意思,我的教材是ret
我试了一下,好像两个都可以.有什么区别吗?
Joke_Olive 2007-11-06
  • 打赏
  • 举报
回复
侯佩没有多打个 f
retf 是远调用返回。

不过,他介绍的这种返回方法是不推荐的方法。
之所以在很多教材中出现,只是因为这些教材中用的例子是从早年的书中一代一代地抄袭过来的。



a19861028 2007-11-06
  • 打赏
  • 举报
回复
123456
G:\xpdos>debug my.exe
-d ds:0 100
1447:0000 CD 20 FF 9F 00 9A F0 FE-1D F0 4F 03 39 0E 8A 03 . ........O.9...
1447:0010 39 0E 17 03 39 0E 28 0E-01 01 01 00 02 FF FF FF 9...9.(.........
1447:0020 FF FF FF FF FF FF FF FF-FF FF FF FF E6 13 4C 01 ..............L.
1447:0030 F9 12 14 00 18 00 47 14-FF FF FF FF 00 00 00 00 ......G.........
1447:0040 05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
1447:0050 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 .!...........
1447:0060 20 20 20 20 20 20 20 20-00 00 00 00 00 20 20 20 .....
1447:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........
1447:0080 00 0D 6D 79 2E 65 78 65-0D 42 4C 41 53 54 45 52 ..my.exe.BLASTER
1447:0090 3D 41 30 0D 64 64 72 65-73 73 2E 20 20 46 6F 72 =A0.ddress. For
1447:00A0 20 65 78 61 6D 70 6C 65-3A 0D 20 6F 6E 20 4E 54 example:. on NT
1447:00B0 56 44 4D 2C 20 73 70 65-63 69 66 79 20 61 6E 20 VDM, specify an
1447:00C0 69 6E 76 61 6C 69 64 0D-20 6F 6E 6C 79 2E 0D 00 invalid. only...
1447:00D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
1447:00E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
1447:00F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
1447:0100 70 p
-

是啊,侯佩多打个f吧.
Joke_Olive 2007-11-06
  • 打赏
  • 举报
回复
你上面的最后一个INT后面没中断号,当然是无效指令
另外,
PUSH DS
XOR AX,AX
PUSH AX
这三条指令放在程序一开始处只是将PSP段地址和偏移量0入栈,需要与远程的RET配合。
INT 20H或0号INT 21H前要求CS指向PSP段,所以只适用于.COM格式的程序,.exe格式是不能直接用的,你无法单独更改CS让它指向PSP段。

RETF的问题,看7楼的回复。
它是要与过程定义配合的。

再次提示:这种模式是一种在有了4CH功能后就被淘汰的模式,编程时不建议使用。

feathergirl 2007-11-06
  • 打赏
  • 举报
回复
我又试了一下,
push ds
xor ax,ax
push ax

;... ...

retf
返回不了dos它会重头运行.

push ds
xor ax,ax
push ax
MOV ah,0
INT
会报无效的操作指令.
Joke_Olive 2007-11-06
  • 打赏
  • 举报
回复
0号DOS系统功能调用返回DOS的要求与INT 20H相同,要求事先将CS指向PSP,否则无法正确返回。
4CH号无需事先将CS指向PSP。

所以,4CH号功能调用功能更强,使用更方便。在3.0版以上的DOS参考手册中建议不要再用0号DOS系统功能调用或INT 20H,改用4CH号调用。
feathergirl 2007-11-06
  • 打赏
  • 举报
回复
MOV ah,0
INT 21H


MOV ah,4ch
INT 21H
有什么区别?
Joke_Olive 2007-11-06
  • 打赏
  • 举报
回复
由标准汇编程序处理时,只要写RET就行了,因为汇编程序会根据PROC定义时的NEAR(可省略)或FAR自动汇编。
但是,实际的RET近调用返回与RETF远调用返回的机器码并不相同。
在DEBUG中,它的汇编必须明确指定是RET还是RETF,反汇编则会根据指令直接显示真实的结果。


上面侯佩说的方式中,省略了程序格式中的将主程序定义为FAR的语句部分。
编程时如果也省略这个FAR,程序是无法正确返回的。





Joke_Olive 2007-11-05
  • 打赏
  • 举报
回复 1
楼上这种push…………retf方法,用于早期低版本的还没有4CH号功能的DOS(高版本的也可以用,但不是标准方法)。
这种方法是用INT 20H结束程序返回DOS的。

用INT 20H返回DOS,有一个前提,就是CS必须指向程序的PSP前缀。
DOS为程序创建的PSP的前两个字节的内容是 CD 20,即INT 20H的机器码。
程序刚装入时,DS指向的是PSP所在段,不是数据段(所以程序才需要在开始部分重新设置DS让它指向数据段)

知道了这个,你再分析一下上面四条指令,就能明白了。

大熊猫侯佩 2007-11-05
  • 打赏
  • 举报
回复
push ds
xor ax,ax
push ax

;... ...

retf
Joke_Olive 2007-11-05
  • 打赏
  • 举报
回复
DOS功能调用的方法,是将功能号放入AH,设置好其它入口参数,然后执行INT 21H

MOV AH, 4CH ;这是设置4CH功能调用号,不能写成4C00H是因为4C00H是16位数存不进8位的AH寄存器。
;如果要设置返回码,可再加下面这一句:
MOV AL, XXH ;这里的XX是返回码的16进制值。一般00表示未出错的正常返回。
INT 21H ;这时即可执行中断指令。

这种设置可以改成:

MOV AX, 4CXXH
INT 21H

上面这种写法结果也是将4CH存入AH寄存器,XXH存入AL寄存器。

在一般的例题程序中,比较常见的语句是:
MOV AX,4C00H
INT 21H
这是返回码为00的调用。


21,497

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧