PDA

View Full Version : سوال: اسمبلی در پاسکال



quiet_programmer
دوشنبه 08 فروردین 1390, 15:31 عصر
با عرض سلام و خسته نباشید.

من میخوام آدرس یه متغییر رو با استفاده inline assembly (اسمبلی درون پاسکال) به استک پوش کنم ولی ارور 155 رو میده. ولی متغییر از نوع integer رو به راحتی میشه پوش کرد.

PROGRAM Test
VAR
a:integer;
b:pointer;
BEGIN
asm
PUSH A
PUSH B {Error 155}
END;
END.

اگه بفرمایین که چه طور میشه بجز نوع داده integer نوع داده ی دیگه رو (مخصوصا نوع داده pointer) هم بشه push کرد ممنونتون میشم.

خیلی خیلی واجبه:گریه:. اگه این اتفاق بیوفته وای ... چی میشه!:کف:

BORHAN TEC
سه شنبه 09 فروردین 1390, 00:53 صبح
من برنامه شما را در Delphi XE چک کردم و اثری از خطا مشاهده نکردم.

vcldeveloper
سه شنبه 09 فروردین 1390, 02:21 صبح
همینطوری push کنید؟! اونها که خودشون روی Stack هستند، مقدار دهی اولیه هم نشدند، میخواید یک متغیری که روی Stack هست و مقدار دهی اولیه نشده رو Push کنید که چی بشه؟!
وقتی inline Assembly کار می کنید، اول از همه باید ببینید کامپایلر چه کدی تولید میکنه، و کد شما در نسبت اون کدهای تولید شده توسط کامپایلر، در چه جایگاهی قرار میگیره، وگرنه کد اسمبلی شما جایی با کدهای تولید شده توسط کامپایلر تداخل پیدا میکنه، و کل برنامه رو به هم میریزه!

quiet_programmer
سه شنبه 09 فروردین 1390, 11:15 صبح
با سلام


همینطوری push کنید؟! اونها که خودشون روی Stack هستند، مقدار دهی اولیه هم نشدند، میخواید یک متغیری که روی Stack هست و مقدار دهی اولیه نشده رو Push کنید که چی بشه؟!این چیزی که من اینجا نوشتم فقط یه مثال بود برای اینکه بگم نوع Pointer پوش نمیشه.

اصلا نوع pointer هیچ. چه جوری میشه نوع real یا string و... رو به استک پوش کرد و بعد دوباره توی همون متغییرها pop کرد. مثل کد زیر که چون نوع داده ای که پوش میشه از نوع integer هست بدن خطا اجرا میشه و خروجی درست رو بدست میده

program test;
var
n:integer;
total1:integer;
total2:integer;
total3:integer;
returnpt:INTEGER;
begin
asm
PUSH N
PUSH TOTAL1
PUSH TOTAL2
PUSH TOTAL3
PUSH RETURNPT
end;

...
...
...

ASM
POP RETURNPT
POP TOTAL3
POP TOTAL2
POP TOTAL1
POP N
END;
end.

اینکه اول گفتم نوع داده پوینتر بخاطر این بود که احتمال میدادم نوع های دیگه به استک پوش نشه مثلا نوع داده ای که کاربر تعریف کرده باشه. به همین خاطر بود که گفتم اگه نشه خود متغییر رو پوش کرد آدرس متغییر رو پوش کنم و بعد دوباره از استک برش دارم.


وقتی inline Assembly کار می کنید، اول از همه باید ببینید کامپایلر چه کدی تولید میکنه،از کجا میشه فهمید که کامپایلر چه کدی به اسمبلی تولید میکنه. کامپایلری که من استفاده میکنم Turbo pascal v.7.


من برنامه شما را در Delphi XE چک کردم و اثری از خطا مشاهده نکردم. ممنون از توجه شما. ولی من تو کامپایلر turbo pascal v.7 full میخوام این کارو انجام بدم

quiet_programmer
دوشنبه 15 فروردین 1390, 14:13 عصر
خیلی ممنونم از دوستان که اینقدر کمک میکنن و مارو شرمنده خودشون.:متعجب:

مشکل حل شد. کدش رو میزارم تا احیانا بکارتون بیاد. خیلی هم سخت نبود ولی یکم باید اسمبلی بلد میبودم که بلاخره تونستم.

لطفا این جمله رو تکرار نکنین که میخواید یک متغیری که روی Stack هست و مقدار دهی اولیه نشده رو Push کنید که چی بشه؟!.
با این مثال ساده فقط میخوام ایده بدم. همین!
تو این کد یه متغییر از نوع real رو push میکنم به استک و دوباره پاپ میکنم میزارم تو یه متغییر دیگه از نوع real. به جای نوع real هم میتوننین از انواع نوع داده های دیگه حتی نوع تعریف شده توسط کاربر هم استفاده کنین.

PROGRAM Test;
VAR
Rel,Rel2:Real;
Size:Integer;
BEGIN
Rel:=3.14;
Size:=SizeOf(Rel);
ASM

MOV SI,OFFSET Rel
MOV CX,Size
@1:
CMP CX,0
JE @EXIT
CMP CX,1
JE @PU1B
MOV AX,[SI]
PUSH AX
ADD SI,2
SUB CX,2
JMP @1
@PU1B:
MOV AX,0
MOV AL,[SI]
PUSH AX
@EXIT:


{.....}
{.....}

MOV SI,OFFSET Rel2
MOV CX,Size
ADD SI,CX
@2:
CMP CX,0
JE @EXPOP
CMP CX,1
JE @PO1B
SUB CX,2
SUB SI,2
POP AX
MOV [SI],AX
JMP @2
@PO1B:
SUB SI,1
POP AX
MOV [SI],AL
@EXPOP:
END;
Writeln(Rel);
Writeln(Rel2);
Readln;

END.