PDA

View Full Version : Uso dello stack in asm x86


Luc@s
27-08-2004, 20:34
; Source name : CHARSIN.ASM
; Executable name : CHARSIN
; Version : 1.0
; Created date : 11/21/1999
; Last update : 11/30/1999
; Author : Jeff Duntemann
; Description : A data input demo for Linux, using NASM 0.98
;
; Build using these commands:
; nasm -f elf charsin.asm
; gcc charsin.o -o charsin
;
[SECTION .text] ; Section containing code
extern stdin ; Standard file variable for input
extern fgets
extern printf
extern scanf
global main ; Required so linker can find entry point
main:
push ebp ; Set up stack frame for debugger
mov ebp,esp
push ebx ; Program must preserve ebp, ebx, esi, & edi
push esi
push edi
;;; Everything before this is boilerplate; use it for all ordinary apps!
;; First, an example of safely limited string input using fgets. Unlike
;; gets, which does not allow limiting the number of chars entered, fgets
;; lets you specify a maximum number. However, you must also specify a
;; file (hence the 'f' in 'fgets') so we must push the stdin handle.
push dword sprompt ; Push address of the string input prompt string
call printf ; Display it
add esp,4 ; Clean up stack for 1 arg
push dword [stdin] ; Push predefined file handle for standard input
push dword 72 ; Accept no more than 72 characters from keybd.
push dword instring ; Push address of buffer for entered characters
call fgets ; Call fgets
add esp,12 ; 3 args X 4 bytes = 12 for stack cleanup
push dword instring ; Push address of entered string data buffer
push dwrod sshow ; Push address of the string display prompt
call printf ; Call printf
add esp,8 ; Clean up the stack
;; Next, we'll use scanf to enter numeric data. This is easier, because
;; unlike strings, integers can only be so big and hence are self-
;; limiting.
push dword iprompt ; Push address of the integer input prompt
call printf ; Display it
add esp,4 ; Clean up the stack
push dword intval ; Push the address of the integer buffer
push dword iformat ; Push the address of the integer format string
call scanf ; Call scanf to enter numeric data
add esp,8 ; Clean up the stack
push dword [intval] ; Push integer value to display
push dword ishow ; Push base string
call printf ; Call printf to convert & display the integer
add esp,8 ; Clean up the stack
;;; Everything after this is boilerplate; use it for all ordinary apps!
pop edi ; Restore saved registers
pop esi
pop ebx
mov esp,ebp ; Destroy stack frame before returning
pop ebp
ret ; Return control to Linux
[SECTION .data] ; Section containing initialized data
sprompt db 'Enter string data, followed by Enter: ',0
iprompt db 'Enter an integer value, followed by Enter: ',0
iformat db '%d',0
sshow db 'The string you entered was: %s',10,0
ishow db 'The integer value you entered was: %5d',10,0
[SECTION .bss] ; Section containing uninitialized data
intval resd 1 ; Reserve one uninitialized double word
instring resb 128 ; Reserve 128 bytes for string entry buffer


In base a sto code io capisco come usare lo stack x le funz del c........ma per le mie proc come faccio???

AnonimoVeneziano
28-08-2004, 01:26
Che roba è la tua proc? :D

Comunque ti consiglio bene o male di seguire sempre la calling convention del C , che è quella standard sotto linux .

In particolare sotto un sistema UNIX quando crei una tua funzione devi fare in modo che questa salvi i valori di EBX, ESI, EDI, EBP, ESP nello stack , perchè questi registri devono rimanere inalterati per convenzione (quindi se vuoi usare questi registri nel corpo della funzione devi salvarli nello stack per non perderne il contenuto :) ) e poi prima del "ret" li "poppi" di nuovo . Poi le convenzioni C prevedono altre cose , come valore di ritorno in EAX e altre robe del genere, comunque è tutto spiegato nel libro che stai seguendo .

Ciao

Luc@s
28-08-2004, 07:55
Originariamente inviato da AnonimoVeneziano
Che roba è la tua proc? :D


Una procedura scritta da me :D

repne scasb
29-08-2004, 20:54

Luc@s
29-08-2004, 22:32
spiegati un attimo meglio che mi interessa assai :D

repne scasb
30-08-2004, 08:30

Luc@s
30-08-2004, 08:37
Esercizio per il volenteroso Luc@s:

Riscrivere il codice piu' sopra leggibile, in modo che: i 3 parametri di ritorno non sovrascrivano i 3 valori passati dall procedura padre (hai la piu' completa liberta' d'azione).

Ci penso e poi ti posto la mia soluzione.
Stamani non posso lavorare, devo fare i compiti(la scuola inizia l'8 per me), indi te la mandero oggi pome;)

P.S: tnk per l'attenzione che mi dai :D

Luc@s
30-08-2004, 11:56
; Procedura padre

mov edi,MyStack
mov [edi],Val1 ; 0h
add edi,4h
mov [edi],Val2 ; 4h
add edi,4h
mov [edi],Val3 ; 8h
call MyProc
...
; lavoro con eax, ebx e ecx modificati dalla funz e poi li ripristino

pop eax
pop ebx
pop ecx
...
...

; Procedura figlia (MyProc)

mov eax,[edi]
mov ebx,[edi-4h]
mov ecx,[edi-8h]
push eax
push ebx
push ecx

; Il codice della routine MyProc

...
...

; Ritorni 3 valori alla routine padre
mov [edi],eax
mov [edi-4h],ebx
mov [edi-8h],ecx
ret


Cosi non ha molto senso vero?

repne scasb
30-08-2004, 15:10