Jacek Pieprzak Rzeszów 31.10.2011r.
L04
Programowanie niskopoziomowe
Sprawozdanie z laboratorium
Temat: Zmienne, adresy, wskaźniki
Kod programu analizowanego na zajęciach:
char c,c1,c2;
int i;
char Tabl[10];
char Napis[] = "asembler";
char *ptr;
struct hilo {char l; char h;};
union u1 { int i;
struct hilo c;};
union u1 utab[4];
union u1 *uptr;
void main(void)
{
c=1;
i=-1;
ptr=Tabl;
*ptr++=1;
*ptr++=2;
c=*((ptr--)-1);
utab[0].i =0x2211;
utab[1].c.l=0x33;
utab[1].c.h=0x44;
utab[2].c.l=0x55;
utab[2].c.h=0x66;
ptr=(char *)&utab[0];
i=*(ptr+1);
ptr = (char *) ((union u1 *)ptr+1);
c1=*ptr++;
c2=*ptr++;
uptr = utab;
i=(uptr+1)->i;
uptr++;
i=(uptr+1)->i;
}
Kod dla modelu typu Small
//Pozwala na asemblowanie jeśli nazwa została zdefiniowana.
ifndef ??version
//Makroinstrukcja
?debug macro
endm
publicdll macro name
public name
endm
endif
?debug V 300h
?debug S "..\USER\MAIN.CPP"
?debug C E91253583B102E2E5C555345525C4D41494E2E435050
//deklaracja segmentu typu byte, o typie łączenia public i klasie `CODE', o nazwie _TEXT
_TEXT segment byte public 'CODE'
//koniec deklaracji segmentu
_TEXT ends
//wiązanie segmentu _DATA, _BSS w jedną grupe DGROUP
DGROUP group _DATA,_BSS
//przypisanie etykiet rejestrom cs i ds
assume cs:_TEXT,ds:DGROUP
//deklaracja segmentu typu byte
_DATA segment word public 'DATA'
//przypisanie etykiet danym typom
d@ label byte
d@w label word
_DATA ends
//deklarascja segmentu _BSS
_BSS segment word public 'BSS'
b@ label byte
b@w label word
//przypisanie etykiet zmiennym oraz deklaracja zmiennej o rozmiarze 1 bajta, wypełniona //nieokreślonymi wartościami
_c label byte
db 1 dup (?)
_c1 label byte
db 1 dup (?)
_c2 label byte
db 1 dup (?)
//przypisanie etykiety _i zmiennej typu word oraz deklaracja zmiennej o rozmiarze 2 bajtów, //wypełniona nieokreślonymi wartościami
_i label word
db 2 dup (?)
//przypisanie etykiety _Tabl oraz deklaracja tablicy o rozmiarze 10 bajtów, wypełniona //nieokreślonymi wartościami
_Tabl label byte
db 10 dup (?)
//koniec deklaracji segmentu _BSS
_BSS ends
//deklaracja segmentu danych
_DATA segment word public 'DATA'
//przypisanie etykiety _Napis do zmiennej typu byte, oraz wpisanie do niej wartości hex //odpowiadające napisowi zadeklarowanemu w programu w kodzie ASCII
_Napis label byte
db 97
db 115
db 101
db 109
db 98
db 108
db 101
db 114
db 0
_DATA ends
//deklaracja pozostałych elementów,
_BSS segment word public 'BSS'
_ptr label word
db 2 dup (?)
_utab label word
db 8 dup (?)
_uptr label word
db 2 dup (?)
_BSS ends
//deklaracja segmentu kodu
_TEXT segment byte public 'CODE'
;
; void main(void)
;
//przypisanie etykiety _TEXT rejestru cs
assume cs:_TEXT
//deklaracja procedury _main, wywoływanie bliskie (w tym samym segmencie kodu)
_main proc near
//położenie rejestru bp na stosie
push bp
//umieszczenie w rejestrze bp wartości wskaźnika stosu
mov bp,sp
//przypisanie do zmiennej _c typu byte wartości 1, operator ptr wymusza zmianę wielkości //operandu w tym przypadku na byte ponieważ zmienna c jest typu char, jest jednobajtowa
;
; {
; c=1;
;
mov byte ptr DGROUP:_c,1
//przypisanie do zmiennej _i wartości -1, operator ptr wymusza zmianę wielkości operandu w //tym przypadku na word ponieważ zmienna _i jest typu int
;
; i=-1;
;
mov word ptr DGROUP:_i,-1
//zapisanie adresu pierwszego elementu tablicy _Tabl do _ptr
;
; ptr=Tabl;
;
mov word ptr DGROUP:_ptr,offset DGROUP:_Tabl
//zapisanie do bx wartosci _ptr
//wpisanie do bx wartości 1
//zwiększenie adresu _ptr o 1
;
; *ptr++=1;
;
mov bx,word ptr DGROUP:_ptr
mov byte ptr [bx],1
inc word ptr DGROUP:_ptr
//zapisanie do bx wartosci _ptr
//wpisanie do bx wartości 2
//zwiększenie adresu _ptr o 1
;
; *ptr++=2;
;
mov bx,word ptr DGROUP:_ptr
mov byte ptr [bx],2
inc word ptr DGROUP:_ptr
//zapisanie do bx adresu _ptr
//zapisanie do al starszczej częsci znajdującej się w bx
//wpisanie al do zmiennej _c
//zmiejszenie adresu _ptr o 1
;
; c=*((ptr--)-1);
;
mov bx,word ptr DGROUP:_ptr
mov al,byte ptr [bx-1]
mov byte ptr DGROUP:_c,al
dec word ptr DGROUP:_ptr
//wpisanie wartości 87211 do unii do zmiennej utab[0].i
;
; utab[0].i =0x2211;
;
mov word ptr DGROUP:_utab,8721
//ponieważ utab[0].i jest dwubajtowe, następne przypisanie odbędzie się 2 bajty dalej w //_utab+2
;
; utab[1].c.l=0x33;
;
mov byte ptr DGROUP:_utab+2,51
//utab[1].c.l jest charem, jest jednobajtowe, więc kolejnene przypisanie następuje 1 bajt dalej //niż poprzednio _utab+3
;
; utab[1].c.h=0x44;
;
mov byte ptr DGROUP:_utab+3,68
;
; utab[2].c.l=0x55;
;
mov byte ptr DGROUP:_utab+4,85
;
; utab[2].c.h=0x66;
;
mov byte ptr DGROUP:_utab+5,102
//wskaźnik ptr pokazuje na pierwsze pole unii utab przekonwertowanej na char
;
; ptr=(char *)&utab[0];
;
mov word ptr DGROUP:_ptr,offset DGROUP:_utab
// do bx przypisywany jest adres wskaźnika _ptr, następnie do al wpisywany jest ten adres //większy o 1. Ponieważ zmienna int jest intem, należy przekonwertować ten bajt na słowo w ax. //Robi to komenda cbw. Po tej operacji można zapisać wartość z ax do zmiennej _i
;
; i=*(ptr+1);
;
mov bx,word ptr DGROUP:_ptr
mov al,byte ptr [bx+1]
cbw
mov word ptr DGROUP:_i,ax
// _ptr do ax, poprzez konwersje traktujemy ptr jako unie u1. Jako, że stosujemy konwersje na //u1, do adresu wskaźnika musimy dodac 2 w celu pokazania na następny element. Na końcu //przypisujemy tego ax do _ptr
;
; ptr = (char *) ((union u1 *)ptr+1);
;
mov ax,word ptr DGROUP:_ptr
add ax,2
mov word ptr DGROUP:_ptr,ax
// _ptr do bx, do c1 chcemy przypisac wskaźnik więc do al wpisujemy tylko młodszą część //adresu z bx bo _c1 jest charem, na koniec można wrzucić al do _c1. Została jeszcze //inkrementacja na sam koniec wskaźnika _ptr.
;
; c1=*ptr++;
;
mov bx,word ptr DGROUP:_ptr
mov al,byte ptr [bx]
mov byte ptr DGROUP:_c1,al
inc word ptr DGROUP:_ptr
// to samo co wyżej tylko ze zmienna _c2
;
; c2=*ptr++;
;
mov bx,word ptr DGROUP:_ptr
mov al,byte ptr [bx]
mov byte ptr DGROUP:_c2,al
inc word ptr DGROUP:_ptr
// przypisanie _utab do _uptr
;
; uptr = utab;
;
mov word ptr DGROUP:_uptr,offset DGROUP:_utab
// _uptr do bx, uptr jest wskaźnikiem na unie więc w celu pokazania na następny element //dodajemy 2, a następnie wpisuje tą wartość do _i
;
; i=(uptr+1)->i;
;
mov bx,word ptr DGROUP:_uptr
mov ax,word ptr [bx+2]
mov word ptr DGROUP:_i,ax
// ponieważ wskaźnik na unie jest dwubajtowy, przy jego zwiększaniu dodajemy do adresu 2.
;
; uptr++;
;
add word ptr DGROUP:_uptr,2
// to samo co wyzej
;
; i=(uptr+1)->i;
;
mov bx,word ptr DGROUP:_uptr
mov ax,word ptr [bx+2]
mov word ptr DGROUP:_i,ax
;
; }
;
//zdjecie ze stosu bp, bo main się kończy
pop bp
//powrót z maina
ret
//koniec procedury maina
_main endp
?debug C E9
?debug C FA00000000
//koniec deklaracji segmentu danych
_TEXT ends
//deklaracja segmentu danych
_DATA segment word public 'DATA'
s@ label byte
_DATA ends
//deklaracja segmentu kody
_TEXT segment byte public 'CODE'
_TEXT ends
// zmienne i funkcja main jest dostępna dla innych modułów
public _main
public _uptr
public _utab
public _ptr
public _Napis
public _Tabl
public _i
public _c2
public _c1
public _c
//przypisanie nazwy
_s@ equ s@
//koniec
end
Kod procesora dla modelu typu Large:
Różnice:
//_ptr i _uptr są wskaźnikami, jak widać poniżej w modelu Large są one podwójnymi słowami //czyli czterobajtowe.
_BSS segment word public 'BSS'
_ptr label dword
db 4 dup (?)
_utab label word
db 8 dup (?)
_uptr label dword
db 4 dup (?)
_BSS ends
//wywołanie funkcji main jest wywołaniem dalekim
assume cs:MAIN_TEXT
_main proc far
push bp
mov bp,sp
;
; {
; c=1;
;
mov byte ptr DGROUP:_c,1
;
; i=-1;
;
mov word ptr DGROUP:_i,-1
//Wpisanie do młodszej części ptr wartości ds, oraz wpisanie do starszej części _Tabl
;
; ptr=Tabl;
;
mov word ptr DGROUP:_ptr+2,ds
mov word ptr DGROUP:_ptr,offset DGROUP:_Tabl
//przeniesienie _ptr do pary rejestrów es:bx, bo w modelu large wskaźniki są 4 bajtowe a bx jest //dwu. Wpisanie do tej pary rejestrów wartości 1 oraz inkrementacja _ptr
;
; *ptr++=1;
;
les bx,dword ptr DGROUP:_ptr
mov byte ptr es:[bx],1
inc word ptr DGROUP:_ptr
;
; *ptr++=2;
;
les bx,dword ptr DGROUP:_ptr
mov byte ptr es:[bx],2
inc word ptr DGROUP:_ptr
//przeniesienie _ptr do pary rejestrów es:bx, przeniesienie do al adresu o 1 mniejszego, //przypisanie _c wartości al oraz dekrementacja ptr
;
; c=*((ptr--)-1);
;
les bx,dword ptr DGROUP:_ptr
mov al,byte ptr es:[bx-1]
mov byte ptr DGROUP:_c,al
dec word ptr DGROUP:_ptr
;
; utab[0].i =0x2211;
;
mov word ptr DGROUP:_utab,8721
;
; utab[1].c.l=0x33;
;
mov byte ptr DGROUP:_utab+2,51
;
; utab[1].c.h=0x44;
;
mov byte ptr DGROUP:_utab+3,68
;
; utab[2].c.l=0x55;
;
mov byte ptr DGROUP:_utab+4,85
;
; utab[2].c.h=0x66;
;
mov byte ptr DGROUP:_utab+5,102
//wpisanie do młodszej częsci wskaźnika ds, oraz zapisanie _utab do starszej częsci.
;
; ptr=(char *)&utab[0];
;
mov word ptr DGROUP:_ptr+2,ds
mov word ptr DGROUP:_ptr,offset DGROUP:_utab
//przeniesienie _ptr do es:bx, przeniesienie do al wartościa adresu o 1 większego, konwersja al //na ax oraz wpisanie tej wartości do _i
;
; i=*(ptr+1);
;
les bx,dword ptr DGROUP:_ptr
mov al,byte ptr es:[bx+1]
cbw
mov word ptr DGROUP:_i,ax
//ax-mlodsza czesc wskaznika, bx- starsza czesc, dodanie do dx wartosci 2, wpisanie do //mlodszej czesci ponownie ax oraz do starszej dx.
;
; ptr = (char *) ((union u1 *)ptr+1);
;
mov ax,word ptr DGROUP:_ptr+2
mov dx,word ptr DGROUP:_ptr
add dx,2
mov word ptr DGROUP:_ptr+2,ax
mov word ptr DGROUP:_ptr,dx
// _ptr do es:bx, przeniesienie jednego bajtu es:bx do al, wskazujacego na poczatek _ptr, //zapisanie do _c11 oraz inkrementacja _ptr
;
; c1=*ptr++;
;
les bx,dword ptr DGROUP:_ptr
mov al,byte ptr es:[bx]
mov byte ptr DGROUP:_c1,al
inc word ptr DGROUP:_ptr
;
; c2=*ptr++;
;
les bx,dword ptr DGROUP:_ptr
mov al,byte ptr es:[bx]
mov byte ptr DGROUP:_c2,al
inc word ptr DGROUP:_ptr
//przypisanie do starszej czesci wartości _utab
;
; uptr = utab;
;
mov word ptr DGROUP:_uptr+2,ds
mov word ptr DGROUP:_uptr,offset DGROUP:_utab
// przypisanie _uptr do es:bx, do ax wpsianie wartosci adresu o 2 wiekszego, wskazujacego na //nastepny element, zapisanie ax do _i.
;
; i=(uptr+1)->i;
;
les bx,dword ptr DGROUP:_uptr
mov ax,word ptr es:[bx+2]
mov word ptr DGROUP:_i,ax
//wskazywanie na nastepny element w pamieci
;
; uptr++;
;
add word ptr DGROUP:_uptr,2
;
; i=(uptr+1)->i;
;
les bx,dword ptr DGROUP:_uptr
mov ax,word ptr es:[bx+2]
mov word ptr DGROUP:_i,ax
;
; }
;
pop bp
ret
_main endp