![]() |
Base Pointer
Was macht eigentlich der Base Pointer (BP - Register)? Angeblich zeigt er immer auf den Boden des Stacks? Bei mir ist der aber immer irgendwie 0000h? Wann wir der gesetzt der Base Pointer durch welche Operationen? und wozu wird er verwendet?
soweit ich weiß wird er in Unterprogrammen dazu verwendet auf die übergebenen Argumente zuzugreifen: f1: PUSH BP MOV BP,SP ... MOV BX,[BP] ; gesicherte Base Pointer MOV BX,[BP+2] ; Rücksprungadresse MOV BX,[BP+4] ; 1. Parameter in BX laden MOV AX,[BP+6] ; 2. Parameter in AX laden ... POP BP RET ist das aber alles? und muss ich den wie hier immer manuell setzen? |
Re: Base Pointer
Du hast schon Recht mit deinen Vermutungen.
BP wird als Zeiger auf den Stack-Frame benutzt. Ein Grund dafür ist, dass es im 16-Bit-Modus keine Adressierungsmöglichkeiten über SP (den eigentlichen Stackzeiger) gibt. Darum benutzt man für Routinen mit Parametern oft das folgende Schema:
Code:
Dafür gibt's übrigens auch die Befehle enter und leave (die im Grunde genau das machen).
push bp
mov bp, sp sub sp, 8 ; <-- nur bei lokalen Variablen ; jetzt ist ; [bp] der alte Wert von BP ; [bp+2] die Rücksprungadresse ; [bp+4] der erste Parameter ; [bp+6] der zweite Parameter ; [bp-2] die erste lokale Variable ; [bp-4] die zweite lokale Variable mov sp, bp ; <-- nur wenn man sich bzgl. SP nicht sicher sein kann pop bp ret Im 32-Bit Modus wird oft direkt über ESP adressiert, da dies hier möglich ist. |
Re: Base Pointer
Zitat:
ist Stack-Frame = der Teil von Stack-Segment, den die aktuelle Prozedure verwendet? was heißt es gibt keine Adressierungsmöglichkeiten über SP? |
Re: Base Pointer
Im 16-Bit Modus gibt es *NUR* die folgenden Adressierungsmodi:
Code:
Hierbei bedeutet "+byte" (-128 .. +127) und "+word" (-32768..+32767).
| M o d |
R/M | 0 | 1 | 2 | ----+---------+--------------+--------------+ 000 | [BX+SI] | [BX+SI+byte] | [BX+SI+word] | 001 | [BX+DI] | [BX+DI+byte] | [BX+DI+word] | 010 | [BP+SI] | [BP+SI+byte] | [BP+SI+word] | 011 | [BP+DI] | [BP+DI+byte] | [BP+DI+word] | 100 | [SI] | [SI+byte] | [SI+word] | 101 | [DI] | [DI+byte] | [DI+word] | 110 | [word] | [BP+byte] | [BP+word] | 111 | [BX] | [BX+byte] | [BX+word] | ----+---------+--------------+--------------+ Du kannst Parameter also nicht über [SP+4] adressieren. Zur Begriffsklärung: der Stackframe ist der Bereich des Stacks, der von einer Prozedur benutzt wird. Dabei liegt irgendwo auf dem Stack ja die Rücksprungadresse zur aufrufenden Prozedur. Oberhalb dessen liegen die Parameter, die diese Prozedur für uns auf den Stack gepusht hat. Unterhalb dessen liegen die lokalen Variablen unserer Prozedur. Beispiel: Sagen wir mal, SP ist bei 1234 (hex). Jetzt wird unsere Prozedur aufgerufen mit "Proc(1, 4, 7)". In Assembler ist das:
Code:
Der Stack sieht dann wie folgt aus:
push 1
push 4 push 7 call Proc
Code:
Jetzt können wir unsere Parameter nicht mit [SP+2] oder [SP+4] adressieren, da es einen solchen Adressierungsmodus nicht gibt. Darum benutzt man BP als Zeiger auf den Stackframe. Wir führen aus:
1232 | 0001 <- 1. Parameter
1230 | 0004 <- 2. Parameter 122E | 0007 <- 3. Parameter 122C | 8341 <- Rücksprungadresse <- SP
Code:
und der Stack hat:
push bp
mov bp, sp
Code:
Jetzt haben wir über [BP+8], [BP+6] und [BP+4] Zugriff auf die Parameter. Wenn wir lokale Variablen brauchen, dann belegen wir auch dafür Platz auf dem Stack, und zwar am unteren Ende des Stackframes:
1232 | 0001 <- 1. Parameter
1230 | 0004 <- 2. Parameter 122E | 0007 <- 3. Parameter 122C | 8341 <- Rücksprungadresse 122A | 124A <- alter BP <- [b]SP[/b] <- [b]BP[/b]
Code:
...und der Stack ist 8 Bytes nach unten gerutsch:
sub sp, 8 ; 4 WORD
Code:
Diese Variablen können wir über [BP-2], [BP-4], [BP-6] und [BP-8] adressieren.
1232 | 0001 <- 1. Parameter
1230 | 0004 <- 2. Parameter 122E | 0007 <- 3. Parameter 122C | 8341 <- Rücksprungadresse 122A | 124A <- alter BP <- [b]BP[/b] 1228 | 7777 ; Zufallswerte 1226 | 5555 1224 | 3333 1222 | 8765 <- [b]SP[/b] Jetzt können wir munter lustig vor uns hin programmieren, andere Prozeduren aufrufen usw. Am Ende räumen wir einfach den Stack wieder auf und springen zurück:
Code:
Ich hoffe, das war jetzt etwas deutlicher. Wenn du einen Debugger hast, dann steppe so ein Programm mal in Einzelschritten durch.
mov sp, bp ; löscht alle lokalen Variablen
pop bp ; stellt BP wieder her ret 6 ; springt zurück und löscht die Parameter vom Stack |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:20 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz