الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

الوصول الى المتغيرات بواسطة المسجل ebp

بدأه fouad2008 في 24 نوفمبر 2012 · 6 رد · 735 مشاهدة · في لغة C و ++C
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

لماذا عندما الغي التحسينات (optimization ) يشتغل الكود عادي و عندما افعلها لا يشتغل

int  add(int a, int b)
{
  int rs;
      asm("mov 8(%ebp),%eax");
     asm("add 12(%ebp),%eax");
     asm("mov %eax, -4(%ebp)");
   return rs;
}

اليس ebp دائما يؤشر على بداية الدالة و ebp+8 هو عنوان اول متغير في stack ؟

#2

السلام عليكم

مرحبا أخي الكريم :)

صحيح, الكود يعمل بدون الــ Optimization فقط (أنا أستخدم النسخة 4.6.2 من GCC)

post-219439-031785800 1353762842_thumb.p

أعتقد أن السبب في عدم عمل الكود يعود إلى أن بعض الــ Optimization في الــ GCC تضع بعض الحمايات على الــ Stack (مثل إضافة أو عكس بعض مناطق الذاكرة) مما يجعل الأمور أكثر تعقيداً في بعض الأحيان. هذه الحمايات تُعرف اختصاراً بــ SSP و هي اختصار لــ Stack Smashing Protection.

هذا من جهة, من جهة أخرى أنصحك باستخدام الــ Debugger عند إدخال أوامر ASM في C من أجل ضمان تنفيذ كافة العمليات المطلوبة لأنك أنت من سيُراقب سير تلك العمليات الواحدة تلو الآخرى ..

أفضل طريقة للتعامل مع أوامر أسمبلي في السي تكون باستخدام GDB مُرفق مع ملف إعدادات مثل .gdbinit

هذه الطريقة ستُتيح لك ترجمة الأكواد بحرية أكثر حيث تستطيع التحكم في الــ Stack كيفما تشاء.

و هذا مثال على الخيارات المُتاحة :

Sn@CkeR# gcc stack_frame.c -w -O0 -ggdb -std=c99 -static

-D_FORTIFY_SOURCE=0 -fno-pie -Wno-format -Wno-format-security

-fno-stack-protector -z norelro -z execstack -o stack_frame

بالمناسبة, توجد عدة طرق للجمع, بالنسبة لي أفضل هذه :

#include<stdio.h>

int add(int x, int y) {
    int resultat = 0;
    asm volatile ("mov %1, %2; addl %3, %2" :
                "=a"(resultat) :
                "b"(x), "a"(resultat), "c"(y));
    return resultat;
}

int main() {
    printf("%d", add(4, 6));
    return 0;
}

بالتوفيق.

المرفقات
Example.png
#3

شكرا اخ Sn@CkeR

كنت اعتقد ان stack frame لا علاقة له بالتحسينات . لكن يبدو ان هناك امور كثيرة تحدث

اعلم ان الطريقة الوحيدة هي استخدام extended inline assembly لكن مشكلته الوحيدة انه لديه syntax غريبة و متعبة لكن في نفس الوقت امنة

#4

التحسين لاعلاقة له بالحماية , هذا برنامجك قبل تفعيل التحسين:

#include <stdio.h>

int add(int a, int b)
{
    int x;

    asm("mov 8(%ebp),%eax");
    asm("add 12(%ebp),%eax");
    asm("mov %eax, 4(%ebp)");

    return x;
}


int main(int argc, char **argv)
{
    printf("%d", add(4, 3));

    return 0;
}

إنظر للبرنامج الناتج:

>gdb -q a.exe
(gdb) disassemble main
Dump of assembler code for function main:
   0x004013a0 <+0>:     push   %ebp
   0x004013a1 <+1>:     mov    %esp,%ebp
   0x004013a3 <+3>:     and    $0xfffffff0,%esp
   0x004013a6 <+6>:     sub    $0x10,%esp
   0x004013a9 <+9>:     call   0x4018f8 <__main>
   0x004013ae <+14>:    movl   $0x3,0x4(%esp)
   0x004013b6 <+22>:    movl   $0x4,(%esp)
   0x004013bd <+29>:    call   0x40138c <add>       <- add هناك إستدعاء للدالة
   0x004013c2 <+34>:    mov    %eax,0x4(%esp)       <- دفع القيمة المعادة للمكس
   0x004013c6 <+38>:    movl   $0x403064,(%esp)     <- دفع مؤشر النص
   0x004013cd <+45>:    call   0x401b30 <printf>    <- printf("%d\n", *eax);
   0x004013d2 <+50>:    mov    $0x0,%eax
   0x004013d7 <+55>:    leave
   0x004013d8 <+56>:    ret
   0x004013d9 <+57>:    nop
   0x004013da <+58>:    nop
   0x004013db <+59>:    nop
End of assembler dump.
(gdb) disassemble add
Dump of assembler code for function add:
   0x0040138c <+0>:     push   %ebp                 <- الدالة لها إطارها الخاص
   0x0040138d <+1>:     mov    %esp,%ebp
   0x0040138f <+3>:     sub    $0x10,%esp
   0x00401392 <+6>:     mov    0x8(%ebp),%eax
   0x00401395 <+9>:     add    0xc(%ebp),%eax
   0x00401398 <+12>:    mov    %eax,-0x4(%ebp)
   0x0040139b <+15>:    mov    -0x4(%ebp),%eax      <- eax القيمة المعادة ستكون في المسجل
   0x0040139e <+18>:    leave
   0x0040139f <+19>:    ret
End of assembler dump.
(gdb)

الدالة add موجودة وتقرأ المتغيرات الممرة لها وتعيدها في المسجل eax.

عند تفعيل التحسين, فأنت تسمح للمصرف بتغيير بنية برنامجك حسب مايراه أفضل لتوليد برنامج أصغر وأسرع, إنظر للكود الناتج بعد تفعيل التحسين:

> gdb -q a.exe
(gdb) disassemble main
Dump of assembler code for function main:
   0x00401b7c <+0>:     push   %ebp
   0x00401b7d <+1>:     mov    %esp,%ebp
   0x00401b7f <+3>:     and    $0xfffffff0,%esp
   0x00401b82 <+6>:     sub    $0x10,%esp
   0x00401b85 <+9>:     call   0x4018b4 <__main>
   0x00401b8a <+14>:    mov    0x8(%ebp),%eax       <-+-- !تقرأ الآن متغير الدالة الرئيسية
   0x00401b8d <+17>:    add    0xc(%ebp),%eax       <-+
   0x00401b90 <+20>:    mov    %eax,-0x4(%ebp)
   0x00401b93 <+23>:    movl   $0x0,0x4(%esp)       <- هذا الصفر الذي يظهر لك | pushl $0
   0x00401b9b <+31>:    movl   $0x403064,(%esp)     <- مؤشر النص
   0x00401ba2 <+38>:    call   0x401aec <printf>    <- printf("%d\n", 0);
   0x00401ba7 <+43>:    xor    %eax,%eax
   0x00401ba9 <+45>:    leave
   0x00401baa <+46>:    ret
   0x00401bab <+47>:    nop
End of assembler dump.
(gdb) disassemble add
Dump of assembler code for function add:
   0x0040138c <+0>:     mov    0x8(%ebp),%eax       <- add لاوجود للدالة
   0x0040138f <+3>:     add    0xc(%ebp),%eax
   0x00401392 <+6>:     mov    %eax,-0x4(%ebp)
   0x00401395 <+9>:     xor    %eax,%eax
   0x00401397 <+11>:    ret
End of assembler dump.
(gdb)

بنيت برنامجك تغيرت فالدالة add إختفت وُدمجت مع الدالة الرئيسية.

#5
اقتباس
التحسين لاعلاقة له بالحماية

معك حق :)

الــ SSP وُضعت أساساً للحد من هجمات الــ Buffer overflow.

لكن في النهاية, يبقى تفعيل الــ Optimization غير مُحبب عند استخدام أوامر ASM في C لأن الهدف الرئيسي من إدخال الأسمبلي في السي هو إجراء تحسينات للكود على مستوى الذاكرة و سرعة التنفيذ أيضا و بالتالي من الخطأ تشغيل الــ Optimization في هذه الحالة.

1 −1
#6

شكرا Mr.B

عند تفعيل التحسينات المترجم يحول الدالة الى inline اي يتم وضع الكود مباشرة في مكان الاستدعاء

وجدت طريقة و هي تحويل المتغير rs الى volatile و منع المترجم من تحويل الدالة الى inline

int  __attribute__((noinline)) add(int a, int b)
{
  int volatile rs;
     asm("mov 8(%ebp),%eax");
     asm("add 12(%ebp),%eax");
     asm("mov %eax, -4(%ebp)");
   return rs;
}
#7

@fouad2008

الكود الذي وضعتُه لك بالأعلى يعمل في كلتا الحالتين, سواء كانت الــ Optimization مُفعلة أو لا.

مواضيع مشابهة