Klasy, metody wirtualne w asemblerze

0

Witam,
chciałbym stworzyć program taki jak poniżej, ale napisany w asemblerze:

using namespace std;
class cKlasa {
    public:
    int a;
    int b;
    virtual int dodaj(){
    }
};
class cKlasaPochodna    :public cKlasa{
    public:
    int dodaj(){
        return(a+b);
    }
};
int main(){
    cKlasaPochodna obiekt;
    obiekt.a=2;
    obiekt.b=4;
    obiekt.dodaj();
}

Niestety nie mam pojęcia jak w Asemblerze tworzy się klasy, to co stworzyłem do tej pory, to taki program napisany w VS:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Program Name:           Template.asm

; Program Description:
; Author:
; Date:

.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD



.data
; declare variables here

.code
_this$ = -4                                   ; size = 4
_sStruktura_dodaj PROC                      ; sStruktura::dodaj, COMDAT
        push    ebp
        mov     ebp, esp
        push    ecx
        mov     DWORD PTR _this$[ebp], ecx
        mov     eax, DWORD PTR _this$[ebp]
        mov     eax, DWORD PTR [eax]
        mov     ecx, DWORD PTR _this$[ebp]
        add     eax, DWORD PTR [ecx+4]
        mov     esp, ebp
        pop     ebp
        ret     0
_sStruktura_dodaj ENDP                      ; sStruktura::dodaj

_obiekt$ = -8                                     ; size = 8
_main   PROC
        push    ebp
        mov     ebp, esp
        sub     esp, 8
        lea     ecx, DWORD PTR _obiekt$[ebp]
        call    _sStruktura
        lea     ecx, DWORD PTR _obiekt$[ebp]
        call    _sStruktura_dodaj             ; sStruktura::dodaj
        xor     eax, eax
        mov     esp, ebp
        pop     ebp
        ret     0
_main   ENDP

_this$ = -4                                   ; size = 4
_sStruktura PROC                          ; sStruktura::sStruktura, COMDAT
        push    ebp
        mov     ebp, esp
        push    ecx
        mov     DWORD PTR _this$[ebp], ecx
        mov     eax, DWORD PTR _this$[ebp]
        mov     DWORD PTR [eax], 2
        mov     ecx, DWORD PTR _this$[ebp]
        mov     DWORD PTR [ecx+4], 4
        mov     eax, DWORD PTR _this$[ebp]
        mov     esp, ebp
        pop     ebp
        ret     0
_sStruktura ENDP                          ; sStruktura::sStru

INVOKE ExitProcess,0
END _main


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

using namespace std;
struct sStruktura {
int a=2;
int b=4;
int dodaj(){
return (a+b);
};
};

int main(){
sStruktura obiekt;
obiekt.dodaj();
}

Z góry dziękuję, za wszelkie sugestie. Dopiero zaczynam przygodę z programowaniem.

1

Niestety nie mam pojęcia jak w Asemblerze tworzy się klasy

W większości assembly nie występuje pojęcie klasy[1] - jest to koncept wysokopoziomowy, więc tak naprawdę prawidłową odpowiedzią powinno być: nijak, udajesz obiektowość :-)

W tym udawaniu pomoże znajomość vtable.

[1] np. w x86 czy x86-64 nie ma, jest za to w bajtkodzie Javy.

1

Fizneyjne analizy bytekodu Javy

Uznałem, że może w kontekście wątku byc pomocne jako lektura uzupełniająca, np wprowadzany przymus konstruktora, stosunek do klasy rodzicielskiej itd..

0

Teraz zaczynam przygode z MASM, i spróbuję to wykorzystać:
http://www.drdobbs.com/embedded-systems/object-oriented-programming-in-assembly/184408319

0

Potrzebuje pomocy:
Utknąłem na metodach wirtualnych (Przyklad 14 z linku powyżej). Chciałbym stworzyc taki program, że w zależności jakiego typu(czy shape, rect czy circle) to taki dostaniemy komunikat na ekranie.

Shape    struc
ix       dw      ?     ;Wspolrzedna X
iy       dw      ?     ;Wspolrzedna Y
Draw     dd      Shape_Draw     ;Default (overridden) DRAW routine
Shape    ends
;
Rect     struc
         dw      2 dup (?)      ;Reserve space 
         dd      Rect_Draw      ;Draw a rectangle
Rect     ends
;
Circle   struc
         dw      2 dup (?)      ;Reserve space 
         dd      Circle_Draw    ;Draw a circle
Circle   ends

Shape_Draw PROC NEAR
	MOV   AX,@DATA
	MOV   DS,AX
	LEA DX,MSG3         ;print msg3
	MOV AH,09H
	INT 21H
	RET
Shape_Draw ENDP

Rect_Draw PROC NEAR
	MOV   AX,@DATA
	MOV   DS,AX
	LEA DX,MSG1         ;print msg1
	MOV AH,09H
	INT 21H
	RET
Rect_Draw ENDP

Circle_Draw PROC NEAR
	MOV   AX,@DATA
	MOV   DS,AX
	LEA DX,MSG2         ;print msg2
	MOV AH,09H
	INT 21H
	RET
Circle_Draw ENDP

.MODEL SMALL
.DATA
MSG1   DB  "Klasa RECT: ",'$'
MSG2   DB  "Klasa CIRCLE: ",'$'
MSG3   DB  "Klasa SHAPE: ",'$'
MyRect 		rect	<'6','8'>
MyCircle	circle	<'6','7'>
MyShape		shape	<'6','6'>

.CODE


main:   

MOV DX, rect.Rect_Draw
MOV AH, 02h
INT 21H


                       
MOV   AX,@DATA
MOV   DS,AX
LEA DX,MSG1         ;print msg1
MOV AH,09H
INT 21H


MOV AH, 02h
INT 21H
END
0
Shape    struc
ix       dw      ?     ;Wspolrzedna X
iy       dw      ?     ;Wspolrzedna Y
Draw     dd      Shape_Draw     ;Default (overridden) DRAW routine
Shape    ends
;
Rect     struc
         dw      2 dup (?)      ;Reserve space 
         dd      Rect_Draw      ;Draw a rectangle
Rect     ends
;
Circle   struc
         dw      2 dup (?)      ;Reserve space 
         dd      Circle_Draw    ;Draw a circle
Circle   ends

To raczej niepraktyczne podejście z tymi dupami, bo każde dodanie pola wiąże się z koniecznością poprawiania. Raczej przesuń metodę (metody) na sam początek.
W przypadku większej ilości metod możesz trzymać osobny wskaźnik do każdej, ale kompilatory języków wysokiego poziomu (C++) trzymają w obiekcie tylko jeden wskaźnik do tablicy metod wirtualnych (więc niezależnie od ilości metod wskaźnik jest jeden, a sama tablica właściwych wskaźników na metody jest wspólna dla wszystkich obiektów danego typu).

No i metoda powinna dostawać jako jeden z parametrów (na stosie, albo w wybranym przez ciebie rejestrze - zawsze tym samym) wskaźnik na obiekt (this/self).
Wypełnianie wskaźnika w konstruktorze, czyli zdefiniuj procedury np. MakeRect, MakeCircle itp.

0

Przyszło mi do głowy, że warto dodać już gotową wersję dla innych osob, które będę poszukiwały tego co stworzyłem ( poniżej przedstawiam jeden z programów), zwiazany z klasami, metodami w asemblerze:

.MODEL SMALL
.DATA
MSG1   DB  "Obiekt1.output: ",'$'
MSG2   DB  "Obiekt2.output: ",'$'
MSG3   DB  "Narysowano ?shape? Wspolrzedne: ",'$'
MSG4   DB  "Narysowano rect. Wspolrzedne: ",'$'
_THIS       equ       es:[bx]
Shape_Draw  proc      far
    MOV   AX,@DATA
    MOV   DS,AX
    LEA DX,MSG3              ;print msg3
    MOV AH,09H
    INT 21H
    MOV DX, _THIS.ix         
    MOV AH,02            ;code to print a character
    INT 21H
    MOV DX, _THIS.iy         
    MOV AH,02            ;code to print a character
    INT 21H
    ret
Shape_Draw endp
Rect_Draw   proc      far
    MOV   AX,@DATA
    MOV   DS,AX
    LEA DX,MSG4              ;print msg4
    MOV AH,09H
    INT 21H
    MOV DX, _THIS.ix         
    MOV AH,02            ;code to print a character
    INT 21H
    MOV DX, _THIS.iy         
    MOV AH,02            ;code to print a character
    INT 21H
    ret
Rect_Draw endp
Shape    struc
ix       dw      ?          ;Wspolrzedna X
iy       dw      ?          ;Wspolrzedna Y
Draw     dd      Shape_Draw     ;Default (overridden) DRAW routine
Shape    ends
;
Rect     struc
     dw ?
         dw     ?           ;Reserve space 
         dd      Rect_Draw      ;Draw a rectangle
Rect     ends
;
;
Obiekt1 Shape    <'1','2'>
Obiekt2 Rect    <'3','4'>
;
.CODE
MOV   AX,@DATA
MOV   DS,AX
LEA DX,MSG1         ;print msg1
MOV AH,09H
INT 21H

mov      bx, seg Obiekt1
mov      es, bx
mov      bx, offset Obiekt1
CALL Obiekt1.Draw

MOV dl, 10      ;code for print new line
MOV ah, 02h
INT 21h
MOV dl, 13
MOV ah, 02h
INT 21h

MOV   AX,@DATA
MOV   DS,AX
LEA DX,MSG2         ;print msg2
MOV AH,09H
INT 21H

mov      bx, seg Obiekt2
mov      es, bx
mov      bx, offset Obiekt2
CALL Obiekt2.Draw

MOV AH,4CH 
INT 21H
END

1 użytkowników online, w tym zalogowanych: 0, gości: 1