Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Base Pointer (https://www.delphipraxis.net/60309-base-pointer.html)

mumu 5. Jan 2006 06:28


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?

Flocke 5. Jan 2006 08:52

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:
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
Dafür gibt's übrigens auch die Befehle enter und leave (die im Grunde genau das machen).

Im 32-Bit Modus wird oft direkt über ESP adressiert, da dies hier möglich ist.

mumu 5. Jan 2006 09:06

Re: Base Pointer
 
Zitat:

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.
diesen satz versteh ich nicht 100 prozentig.
ist Stack-Frame = der Teil von Stack-Segment, den die aktuelle Prozedure verwendet?

was heißt es gibt keine Adressierungsmöglichkeiten über SP?

Flocke 5. Jan 2006 20:19

Re: Base Pointer
 
Im 16-Bit Modus gibt es *NUR* die folgenden Adressierungsmodi:
Code:
    |               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]   |
----+---------+--------------+--------------+
Hierbei bedeutet "+byte" (-128 .. +127) und "+word" (-32768..+32767).
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:
push 1
push 4
push 7
call Proc
Der Stack sieht dann wie folgt aus:
Code:
1232 | 0001 <- 1. Parameter
1230 | 0004 <- 2. Parameter
122E | 0007 <- 3. Parameter
122C | 8341 <- Rücksprungadresse <- SP
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:
Code:
push bp
mov bp, sp
und der Stack hat:
Code:
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]
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:
Code:
sub sp, 8 ; 4 WORD
...und der Stack ist 8 Bytes nach unten gerutsch:
Code:
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]
Diese Variablen können wir über [BP-2], [BP-4], [BP-6] und [BP-8] adressieren.

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:
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
Ich hoffe, das war jetzt etwas deutlicher. Wenn du einen Debugger hast, dann steppe so ein Programm mal in Einzelschritten durch.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:21 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz