تشخیص ساختارهای برنامه نویسی در اسمبلی - قسمت سوم
توی برنامه نویسی از دستور if برای تغییر روند اجرا مبتنی بر یک شرط خاص استفاده میشه که ما میخوایم اینجا به بررسی کدهای دیس اسمبل تولید شده با دستور if بپردازیم.
در زیر کد زبان سی و همچنین کد دیس اسمبل شده ی اون رو مشاهده میکنید توجه کنید که دستور if در اینجا با پرش شرطی jnz پیاده سازی شده البته توی کدهای دیس اسمبل شده این یادتون باشه که هر پرش شرطی دلیل بر وجود دستور if نیست.int x = 1;
int y = 2;
if(x == y){
printf("x equals y.\n");
}
else{
printf("x is not equal to y.\n");
کد دیس اسمبل شده برنامه بالا:
00401006 mov [ebp+var_8], 1
0040100D mov [ebp+var_4], 2
00401014 mov eax, [ebp+var_8]
00401017 cmp eax, [ebp+var_4] (1)
0040101A jnz short loc_40102B (2)
0040101C push offset aXEqualsY_ ; "x equals y.\n"
00401021 call printf
00401026 add esp, 4
00401029 jmp short loc_401038 (3)
0040102B loc_40102B:
0040102B push offset aXIsNotEqualToY ; "x is not equal to y.\n"
00401030 call printf
توی جلسات قبل من کدهای دیس اسمبل شده رو خط به خط توضیح میدادم ولی فک کنم با توجه به دو جلسه قبل دیگه نیازی به توضیح خط به خط نباشه و فقط قسمت های جدید رو توضیح میدم
همانطور که توی کد بالا میبینید قبل از اجرای دستورات داخل if شرط باید بررسی بشه که در اینجا jnz این وظیفه رو برعهده داره (2)
اما شرط چیه؟ شرط ما برابر بودن دو متغیر هستش و این برابری با دستور cmp بررسی میشه که باید قبل از دستور jnz باشه تا نتیجه مقایسه روی jnz تاثیر بزاره (1)
(شرط پرش jnz چیه؟ اگه دستور cmp پرچم ZF رو یک کنه پرش انجام نمیشه و معنیش اینکه که پرش در صورتی انجام میشه که دو متغیر با هم برابر نباشند)
(اگه با این دستورات آشنا نیستید به قسمت های قبل که توضیح دادم مراجعه کنید)
خوب مشخصه که دو متغیر x و y باهم برابر نیستند پس پرش همیشه انجام میشه و در نتیجه رشته "x is not equal to y.\n" چاپ میشه
به دستور پرش jmp هم دقت کنید که از روی else پرش میکنه (3)
بهتره که همه ی اینهارو توی IDA Pro بصورت گرافیکی بررسی کنید اینطوری موضوع واستون بهتر قابل درک میشه
حالا میخوایم یه شرط تودرتوی if رو بررسی کنیم:
int x = 0;
int y = 1;
int z = 2;
if(x == y){
if(z==0){
printf("z is zero and x = y.\n");
}else{
printf("z is non-zero and x = y.\n");
}
}else{
if(z==0){
printf("z zero and x != y.\n");
}else{
printf("z non-zero and x != y.\n");
}
کد دیس اسمبل شده بالا:
00401006 mov [ebp+var_8], 0
0040100D mov [ebp+var_4], 1
00401014 mov [ebp+var_C], 2
0040101B mov eax, [ebp+var_8]
0040101E cmp eax, [ebp+var_4]
00401021 jnz short loc_401047
00401023 cmp [ebp+var_C], 0
00401027 jnz short loc_401038
00401029 push offset aZIsZeroAndXY_ ; "z is zero and x = y.\n"
0040102E call printf
00401033 add esp, 4
00401036 jmp short loc_401045
00401038 loc_401038:
00401038 push offset aZIsNonZeroAndX ; "z is non-zero and x = y.\n"
0040103D call printf
00401042 add esp, 4
00401045 loc_401045:
00401045 jmp short loc_401069
00401047 loc_401047:
00401047 cmp [ebp+var_C], 0
0040104B jnz short loc_40105C
0040104D push offset aZZeroAndXY_ ; "z zero and x != y.\n"
00401052 call printf
00401057 add esp, 4
0040105A jmp short loc_401069
0040105C loc_40105C:
0040105C push offset aZNonZeroAndXY_ ; "z non-zero and x != y.\n"
00401061 call printf00401061
خوب فک کنم بنظرتون یکم گیچ کننده بیاد ولی تا اونجایی که ممکن باشه ساده توضیح میدم
یادتون هست که jnz اگه دوتا مقدار برابر نباشند پرش میکنه.
اول ما فک میکنیم که تو تا متغیرمون برابر هستند پس:
پرش jnz انجام نمیشه و ما وارد دستورات if میشیم
if(x == y){
داخل if باز هم شرط هست
if(z==0){
و ما فرض میکنیم که z مساوی با صفر هستش پس نباید jnz پرش کنه پس رشته زیر چاپ میشه
printf("z is zero and x = y.\n");
حالا اگه z مساوی صفر نباشه باید jnz پرش کنه و else اجرا بشه در نتیجه
else{
printf("z is non-zero and x = y.\n");
حالا اگه همون اول x مساوی y نباشه jnz پرش میکنه تا دستورات else رو اجرا کنه
}else{
باز داخل else شرط هستش
if(z==0){
اگه این شرط مساوی باشه و jnz پرش انجام نده رشته زیر چاپ میشه
printf("z zero and x != y.\n");
اما اگه z مساوی صفر نباشه و jnz پرش انجام بده دستور else اجرا میشه
else{
printf("z non-zero and x != y.\n");
اگه جایی رو متوجه نشدید بگید تا توضیح بدم
موفق باشید.
Pcrlth0n