简体   繁体   English

当我将堆栈指针值设置为 bp 时,为什么会有 2 字节的偏移量?

[英]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.我想也许你在思考pushpop是如何工作的。 push will decrement sp by 2 and then store a word at the address where sp points. pushsp减 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.因此,如果您正在执行pushpop ,那么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.

相关问题 为什么在移动堆栈指针时出现分段错误? - Why am I getting a segmentation fault when moving the stack pointer? 为什么当我访问由三个整数组成的对象时,它从基本指针中减去而不是从堆栈指针中减去? - Why when I access an object consisting of three integers, does it subtract from the base pointer, and not the stack pointer? 为什么我要向堆栈指针添加地址? - Why I want to add an address to the stack pointer? 当我只有一个4字节的局部变量时,为什么在这种反汇编中堆栈会增加16个字节? - Why stack grows by 16 bytes in this disassembly, when I only have one 4 byte local variable? 为什么在分配没有后续函数调用的大数组时,GCC会将错误的值减去堆栈指针? - Why does GCC subtract the wrong value to the stack pointer when allocating a big array with no subsequent function calls? 设置堆栈段并在装配中偏移 - Set stack segment and offset in assembly 当我使用64位局部变量时,为什么堆栈指针不会减少? - Why doesn't the stack pointer decrease when I am using a 64 bit local variable? 局部变量从堆栈基指针偏移 - Local Variables offset from stack base pointer 为什么我们在汇编中添加一个值来初始化堆栈指针(R7)? - Why we add a value to initialize the stack pointer (R7) in assembly? 为什么在转到下一个堆栈帧时存储旧的帧指针 - Why store the old frame pointer when go to next stack frame
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM