Programowanie niskopoziomowe
Sprawozdanie
Laboratorium 4
Funkcje rekurencyjne i biblioteczne
Wykonujący:
Paweł Ochał
Grzegorz Róg
Jacek Pieprzak
L04
Kod poddany asemblacji:
/* plik do laboratorium 4 z architektury komputerow II */
#include "stdio.h"
/* funkcja rekurencyjna */
unsigned int silnia(int n)
{
if (n<0) return -1;
else if (n==0) return 1;
else return n * silnia(n-1);
}
//prototyp funkcji wieloargumentowej printf
//int printf(const char * format, arg1, arg2,...);
void main(void)
{
int i=3;
i=silnia(i);
printf("%d",i); /* jaka jest kolejnosc parametrow? */
}
Kod assemblera modelu typu Small:
.386p
ifndef ??version
?debug macro
endm
publicdll macro name
public name
endm
endif
?debug V 300h
?debug S "..\USER\MAIN.C"
?debug C E95A908C3B0E2E2E5C555345525C4D41494E2E43
?debug C E9E8BB563B1B443A5C424F524C414E44435C494E434C5544455C53+
?debug C 5444494F2E48
?debug C E9E9BB563B1B443A5C424F524C414E44435C494E434C5544455C5F+
?debug C 444546532E48
?debug C E9E9BB563B1C443A5C424F524C414E44435C494E434C5544455C5F+
?debug C 4E46494C452E48
?debug C E9E9BB563B1B443A5C424F524C414E44435C494E434C5544455C5F+
?debug C 4E554C4C2E48
MAIN_TEXT segment byte public use16 'CODE'
MAIN_TEXT ends
DGROUP group _DATA,_BSS
assume cs:MAIN_TEXT,ds:DGROUP
_DATA segment word public use16 'DATA'
d@ label byte
d@w label word
_DATA ends
_BSS segment word public use16 'BSS'
b@ label byte
b@w label word
_BSS ends
MAIN_TEXT segment byte public use16 'CODE'
;
; unsigned int silnia(int n)
;
assume cs:MAIN_TEXT
_silnia proc far
push bp
mov bp,sp
push si
// procedura _silnia typu far, położenie bp na stosie, ustawienie na nim //wskaźnika sp, położenie na stosie si
mov si,word ptr [bp+6]
;
; {
// Stos: bp, si, si, cs: call _silnia, bp, si
// wpisanie do si bp+6 czyli wartości si ze stosu przesyłanej jako parametr //funkcji
; if (n<0) return -1;
;
or si,si
jge short @1@142
mov ax,00000FFFFh
@1@86:
jmp short @1@254
jmp short @1@254
// suma logiczna dla si; sprawdzenie czy n jest rowne 0, jeśli n większe //bądź równe 0 to skok do etykiety @1@142, jeśli nie to do ax wpisana //zostaje wartość 00000FFFFh (-1). Następnie wykonany zostaje skok //bezwarunkowy do etykiety @1@254 (koniec funkcji)
@1@142:
;
; else if (n==0) return 1;
;
or si,si
jne short @1@226
mov ax,1
jmp short @1@86
jmp short @1@254
// suma logiczna dla si, podobnie jak wyżej; jeśli n<>0 to skok do etykiety //@1@226, jeśli n=0 to do ax wpisana zostaje wartość 1 i wykonany skok do //etykiety @1@86
@1@226:
;
; else return n * silnia(n-1);
;
mov ax,si
dec ax
push ax
push cs
// wpisanie do ax wartości si(zmiennej n), zmiejszenie warości ax o 1, //położenie ax na stosie, położenie cs na stosie, wywołanie funkcji _silnia
call near ptr _silnia
// STOS: bp, si, si, cs: call _silnia, bp, si, ax
pop cx
push ax
// STOS: bp, si, si, cs: call _silnia, bp, si, ax,
//zdjecie jednego elementu ze stosu i położenie ax
pop dx
// STOS: bp, si, si, cs: call _silnia, bp, si, ax,
mov ax,si
// przeniesienie si do ax(n) oraz zdjecie elementu ax ze stosu do //dx(wartość zwrócona z procedury _silnia)
imul dx
// STOS: bp, si, si, cs: call _silnia, bp, si,
// pomnożenie dx przez ax czyli n * wartość zwrócona z procedury _silnia
jmp short @1@86
// skok bezwarunkowy do @1@86
@1@254:
;
; }
;
// koniec procedury _silnia
pop si
pop bp
ret
// STOS: bp, si, si, cs: call _silnia, bp, si
_silnia endp
// STOS: bp, si, si,
;
; void main(void)
;
assume cs:MAIN_TEXT
_main proc far
push bp
mov bp,sp
push si
;
; {
//wywolanie main'a
// STOS: bp
// ustawienie wskaźnika stosu na bp
// STOS: bp, si
// si zawiera zmienna i
; int i=3;
;
mov si,3
// wpisanie do si wartości 3
;
; i=silnia(i);
;
push si
push cs
// położenie na stosie si, cs oraz wywołanie funkcji silnia
call near ptr _silnia
// STOS: bp, si, si, cs: call _silnia
pop cx
// STOS: bp, si, si
// zdjecię si do cx, oraz wpisanie do si wartości zwróconej zawartej w ax
mov si,ax
// STOS: bp, si
;
; printf("%d",i); /* jaka jest kolejnosc parametrow? */
;
push si
push ds
push offset DGROUP:s@
call far ptr _printf
// si,ds oraz offset s@ położone na stosie, wywołanie dalekie funkcji //_printf z biblioteki studio.h
add sp,6
// przemieszczenie wskaźnika stosu o 3 elementy wcześniej
;
; }
;
pop si
pop bp
ret
_main endp
// koniec main'a i zdjęcie ze stosu si oraz bp
?debug C E9
?debug C FA00000000
MAIN_TEXT ends
_DATA segment word public use16 'DATA'
s@ label byte
db '%d'
db 0
_DATA ends
MAIN_TEXT segment byte public use16 'CODE'
MAIN_TEXT ends
public _main
public _silnia
extrn _printf:far
_s@ equ s@
end