[英]Why is there a 2 byte offset when I set the stack pointer value to bp?
I'm learning how to pass parameters to a function via the stack.我正在学习如何通过堆栈将参数传递给函数。 I find myself in a situation where I don't understand why (once I've done the various
pop
's on the stack to save the data), going backwards with the instruction (see DEBUG comments):我发现自己处于一种我不明白为什么的情况(一旦我在堆栈上完成了各种
pop
以保存数据),就按照指令倒退(参见调试注释):
mov ax, [bp + n]
I end up with a 2-byte offset.我最终得到一个 2 字节的偏移量。 I'll explain.
我来解释一下。 I have sketched everything that happens exclusively on the stack.
我已经勾画了只发生在堆栈上的所有事情。 When I get to education:
mov bp, sp
当我开始接受教育时:
mov bp, sp
I copy the address contained in sp
in bp
(which in my case is 00f8h).我将
sp
中包含的地址复制到bp
(在我的例子中是 00f8h)。 Well, it makes me think now that everything I refer to from now on, using [bp + n]
, starts from this address.好吧,这让我觉得从现在开始我所指的一切,使用
[bp + n]
,都是从这个地址开始的。
So, referring to the area that I commented as DEBUG, if bp
= 00f8h and I want to view the content, I should find the byte that I left unchanged with the instruction sub sp, 2
, instead I find myself the starting address that had bp
(2 bytes higher than 00f8h).所以,参考我评论为 DEBUG 的区域,如果
bp
= 00f8h 并且我想查看内容,我应该找到我用指令sub sp, 2
保持不变的字节,而不是我找到自己的起始地址bp
(比 00f8h 高 2 个字节)。
Going on with the next DEBUG statement, I have:继续下一个 DEBUG 语句,我有:
mov ax, [bp + 2]
I should find the value I had memorized of bp
;我应该找到我记住的
bp
值; instead I find myself the return address of the call (4 bytes higher than 00f8h).相反,我发现自己是调用的返回地址(比 00f8h 高 4 个字节)。
The program instruction:程序说明:
mov ax, [bp + 4]
I should find the return address of the procedure call.我应该找到过程调用的返回地址。 Instead I find the value I had saved from the
cx
register.相反,我找到了我从
cx
寄存器中保存的值。
In short, it seems that bp
does not refer to 00f8h but rather to 00fah (2 bytes higher), so that the accounts add up (unfortunately, however, in the registers I see that this is not the case).简而言之,
bp
似乎不是指 00f8h,而是指 00fah(高 2 个字节),因此帐户加起来(但不幸的是,在寄存器中我看到情况并非如此)。
Please do not consider the form in which I try to handle the situation of passing parameters;请不要考虑我尝试处理传递参数情况的形式; my problem is:
我的问题是:
why is there this 2-byte offset?为什么有这个 2 字节的偏移量?
; Use parameterized procedures.
;
;
; To assemble an .ASM file with TASM:
; # TASM PUNTATOR.ASM /L /ZI
; # TLINK PUNTATOR.OBJ /V
dosseg
.model medium
.stack 100h
.data
num1 db 5
num2 db 3
ris db ?
.code
main proc
mov ax, dgroup ; mette il segmento dati in AX
mov ds, ax ; imposta DS in modo da puntare ai dati
xor cx, cx ; I clean up the cx registry
mov cl, num1 ; cx = 5
xor bx, bx ; I clean up the bx registry
mov bl, num2 ; bx = 3
push bx ; 2° parameter
push cx ; 1° parameter
xor ax, ax ; I prepare ax to hold the return parameter
call somma
add sp, 4 ; it's like I'm doing two pops. That is, I restore the
; stack pointer to its original value, before calling
; the two parameters above.
mov ris, al
mov ah, 02h
mov dl, cl ; print cl
add dl, '0'
int 21h
mov ah, 02h
mov dl, '+' ; print '+'
int 21h
mov ah, 02h
mov dl, bl ; print bl
add dl, '0'
int 21h
mov ah, 02h
mov dl, '=' ; print '='
int 21h
mov ah, 02h
mov dl, ris
add dl, '0'
int 21h
mov ah, 4Ch
int 21h ; Return to DOS
main endp
somma proc near
push bp ; I store the base pointer in the stack
mov bp, sp ; copy in bp the address of the stack pointer in this moment
; momento, cioè quando inizia la procedura.
sub sp, 2 ; I save 2 bytes for a local variable
push cx ; I save these two registers because I want to use them as
push dx ; registers for my local parameters, then they will be restored
; DEBUG
xor ax, ax
mov ax, [bp] ; Initial stored address of bp
mov ax, [bp + 2] ; Address of the instruction following the call
mov ax, [bp + 4] ; The value I had put from cx
mov ax, [bp + 6] ; The value I had put from bx
; END DEBUG
mov cx, [bp + 4]
mov dx, [bp + 6]
mov [bp - 2], cx
add [bp - 2], dx
mov ax, [bp - 2]
pop dx
pop cx
mov sp, bp
pop bp
ret
somma endp
end main
I copy the address contained in sp in bp (which in my case is 00f8h).
我将 sp 中包含的地址复制到 bp 中(在我的例子中是 00f8h)。 Well, it makes me think now that everything I refer to from now on, using [bp + n], starts from this address.
好吧,这让我觉得我从现在开始所指的一切,使用 [bp + n],都是从这个地址开始的。
Sure.当然。
So, referring to the area that I commented as DEBUG, if bp = 00f8h and I want to view the content, I should find the byte that I left unchanged with the instruction sub sp, 2, instead I find myself the starting address that had bp (2 bytes higher than 00f8h).
所以,参考我注释为 DEBUG 的区域,如果 bp = 00f8h 并且我想查看内容,我应该找到我用指令 sub sp, 2 保持不变的字节,而不是我找到了自己的起始地址bp(比 00f8h 高 2 个字节)。
That's not right.那是不对的。
I think maybe you have an off-by-one in your thinking about how push
and pop
work.我想也许你在思考
push
和pop
是如何工作的。 push
will decrement sp
by 2 and then store a word at the address where sp
points. push
将sp
减 2 ,然后在sp
指向的地址存储一个字。 pop
is the reverse: load and then increment. pop
是相反的:加载然后递增。 So if you're doing push
and pop
, then sp
will always point to the word which is at the top of the stack, ie the data which was most recently pushed and hasn't been popped.因此,如果您正在执行
push
和pop
,那么sp
将始终指向堆栈顶部的单词,即最近推送但尚未弹出的数据。
Now your function starts with现在你的功能开始于
push bp ; I store the base pointer in the stack
mov bp, sp ; copy in bp the address of the stack pointer in this moment
So if bp
gets the value 00f8h
, then that's the value that was in sp
right after the push
, and this means your stored previous value of bp
is at address 00f8h
.因此,如果
bp
获得值00f8h
,那么这就是push
之后sp
的值,这意味着您之前存储的bp
值位于地址00f8h
。 When you mov ax, [bp]
, you load ax
from address 00f8h
and so you get the old bp
value.当您
mov ax, [bp]
,您从地址00f8h
加载ax
,因此您将获得旧的bp
值。 [bp+2]
contains the return address (located at address 00fah
), [bp+4]
has the first parameter (at 00fch
), [bp+6]
has the second parameter (at 00feh
). [bp+2]
包含返回地址(位于地址00fah
), [bp+4]
包含第一个参数(位于00fch
), [bp+6]
包含第二个参数(位于00feh
)。
Your "unchanged byte" is at the address where sp
pointed after you subtracted 2, namely 00f6h
.您的“未更改字节”位于
sp
减去 2后指向的地址,即00f6h
。 If you want to access it, you need to use address [bp-2]
.如果要访问它,则需要使用地址
[bp-2]
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.