在外部过程中对堆栈进行非活动写入
在一个extern程序中,要求用户输入一个字符串,然后通过堆栈将它返回到main。
字符串在数据段中定义,其名称与主过程文件中的数据段名称不同。
Data_segment_name_ext segment para
ORG 10H
Str DB 20,?,20 DUP (?)
Data_segment_name_ext ends
和堆栈段声明:
Stack_segment_name segment para stack
db 64 dup(0) ;define your stack segment
Stack_segment_name ends
最初在程序开始时我将其声明为public并将BP设置为Stack top:
PUBLIC MyProc
Code_segment_name segment
MyProc PROC FAR
assume SS:Stack_segment_name,CS:Code_segment_name,DS:Data_segment_name_ext
PUSH BP
MOV BP,SP
正在通过函数AH = 0x0A中断0x21
读取字符串LEA DX,Str
MOV AH,0Ah
INT 21H
尝试使用以下循环将字符串保存到堆栈中:
MOV CX,22 ; The string length
MOV SI,00 ; used as an index
TRA1:
DEC BP
MOV AL,Str[SI] ; Str is defined in the data segment
MOV [BP],AL
INC SI
LOOP TRA1
正确读取1-String并将其存储在DS中并且偏移Str [实际字符串在最大长度,实际计数后开始两个字节]
写入字符串中的2- 奇怪的行为:
在循环BP = 0xA4之后,让SP最初= 0xBA(即0xBA-0x16(字符串长度)) 在SS处转储堆栈段:0xA4在SS:SP之前显示8字节的垃圾数据 并且正在编写正确的数据。
如果str ='ABCDEFGHIJ'只有'GHIJ'被保存在堆栈中
>DB SS:0xA4
SS:00A4 00 00 00 00 00 00 00 00 00 00 4A 49 48 47 E7 05 ..........JIHG..
SS:00B4 7E 00 FD 05 02 02 00 00 0A 00 0C 06 B8 E7 05 8E ~...............
注意:060C:在执行远程调用extern过程之前,000A是CS:IP 并成功推送@ SP = 0xC0(即SS:0xBC,SS:0xBD,SS:0xBE,SS:0xBF)
3 - 用MOV [BP]替换MOV [BP],AL,33h会导致相同的行为; 33h不写入旧TOS的前8个字节
4-Enforcing SS(即MOV SS:[BP],AL)在发生相同行为时也无能为力
我知道我可以用其他方式返回参数,但为什么会出现这种情况?
答案 0 :(得分:2)
SP寄存器指示堆栈顶部的当前位置。此加法器下面的所有内容都不在堆栈中。您不能使用SP以下的地址来存储任何数据,因为一旦将任何数据推入堆栈,它将被覆盖(例如,当生成中断时)。
要将局部变量存储在堆栈中,请减少SP(SUB SP, 22
)。这与将22个字节压入堆栈相同。
在过程结束时,您需要释放局部变量。为此,您需要增加SP(ADD SP, 22
)。这将从堆栈中删除22个字节。
完成此操作后,将无法再访问本地变量。
下图显示了堆栈状态:
从步骤4开始,用于“ABC..HJ”字符串的内存不再属于MyProc。在下一步中,该存储器用于处理中断。
无法将数据保存在当前堆栈帧中,并以此方式从过程中返回。
答案 1 :(得分:2)
由于你的过程 MyProc 的目的是通过堆栈返回一个字符串,你不可避免地必须将它存储在call
指令推送到堆栈上的返回地址之上。这段代码可以做到:
sub sp, 22
call MyProc
现在不是通过DS中的额外缓冲区输入,而是直接在堆栈中腾出的空间中简化任务和输入。
mov ax, 20
sub sp, ax
push ax ;This sets up the correct buffer DOS expects
call MyProc
...
MyProc PROC FAR
assume SS:Stack_segment_name,CS:Code_segment_name
PUSH BP
MOV BP,SP
push ds
push ss
pop ds
lea dx, [bp+6]
;String is being read by function AH=0x0A interrupt 0x21
MOV AH,0Ah
INT 21H
pop ds
...
我看到你设置的堆栈只有64个字节。如果您打算在堆栈中存储字符串,我建议您增加此大小。