Trang 1 trên tổng số 3 123 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 25 kết quả

Đề tài: bài tập C khá hay

  1. #1
    Ngày gia nhập
    10 2008
    Bài viết
    85

    Mặc định bài tập C khá hay

    C Code:
    1. #include <stdio .h>
    2.  
    3. void test()
    4. {
    5. // your code here
    6.  
    7. }
    8.  
    9. int main()
    10. {
    11.   int n=100;
    12.   test(); // call test function
    13.  n=0;
    14.   printf("n = %d\n", n);
    15.   return 0;
    16. }

    Các bạn hãy viết hàm test sao cho khi chạy chương trình in ra kết quả "n=100". tại dòng số 6 của hàm main

  2. #2
    Ngày gia nhập
    07 2008
    Nơi ở
    /media/Anime
    Bài viết
    2,288

    Đây là code chạy trên VC6 và DevCpp :

    C++ Code:
    1. #include <stdio.h>
    2.  
    3. void test()
    4. {
    5.     long num = 0;
    6.     long *p = (&num) + 2;
    7.     (*p) += 7;
    8. }
    9.  
    10. int main()
    11. {
    12.     int n = 100;
    13.     test();
    14.     n = 0;
    15.     printf("n = %d\n", n);
    16.     return 0;
    17. }
    Đã được chỉnh sửa lần cuối bởi meoconlongvang : 26-01-2009 lúc 09:50 PM.
    Càng yêu mèo thì mèo càng mập. Mèo càng mập ta lại càng yêu.

  3. #3
    Ngày gia nhập
    11 2008
    Bài viết
    78

    Chà hay quá nhưng không hiểu
    Bạn giải thích đi

  4. #4
    Ngày gia nhập
    02 2008
    Bài viết
    4

    Nhưng cái này nếu dịch theo chế độ debug thì đúng còn chế độ Release thì sai vì mã asm sinh ra hình như sẽ khác nên (*p) += 7; không còn là địa chỉ của cậu lệnh printf trong hàm main nữa . Chắc mục đích của anh mèo là bỏ qua câu lệnh n = 0; để đến thẳng câu lệnh printf sau khi thoát khỏi hàm test
    Đã được chỉnh sửa lần cuối bởi lag_nao : 27-01-2009 lúc 09:47 AM.

  5. #5
    Ngày gia nhập
    07 2008
    Nơi ở
    /media/Anime
    Bài viết
    2,288

    Đúng rồi đó, cách này hơi dở ở chỗ là phụ thuộc vào độ dài câu lệnh tiếp theo sau hàm test
    Càng yêu mèo thì mèo càng mập. Mèo càng mập ta lại càng yêu.

  6. #6
    Ngày gia nhập
    10 2007
    Bài viết
    169

    Mặc định bài tập C khá hay

    - Mình nghĩ có thể thay đổi code của dòng "n = 0;". Nhưng cách này làm trong chế độ protected mode của windows thì cực quá, dùng đến các hàm hệ thống để unlock vùng nhớ, sửa đổi rồi lock lại T_T! Mình cũng không rành mấy hàm này!
    - Với chế độ real mode thì rất dễ:
    VD như dòng : "n = 0;" có address là 0x0042D7AA trên memory, thì trong hàm Test, chúng ta sẻ tạo một pointer đến địa chỉ 0x0042D7AA và cộng thêm 3 bytes!
    C++ Code:
    1. address: 0x0042D7AA  mov dword ptr [n],0
    - Vì 3 ô nhớ: 0x0042D7AA,0x0042D7AA + 1,0x0042D7AA + 2 là dùng để chứa lệnh mov, do đó 4 ô nhớ kế là value cần move vào n!
    - Vì vậy chỉ cần gán: "*p = 100;" thì code của lệnh: "n = 0" sẻ bị thay đỗi thành : "n = 100"! Tóm lại cách này là sẻ thay đổi code của chương trình trên memory!

    - Mình chỉ mới test thử đc với real mode thôi, protected mode thì bị "unhandled exception" vì vùng nhớ của code bị lock.
    Đã được chỉnh sửa lần cuối bởi RadicalLight : 27-01-2009 lúc 05:39 PM. Lý do: Update!

  7. #7
    Ngày gia nhập
    10 2008
    Bài viết
    85

    mình cũng nghĩ là phải cho nó bỏ qua đoạn n=0 nhưng không biết làm như nào, hoặc tác động vào bộ nhớ nhưng không biết cách

  8. #8
    Ngày gia nhập
    07 2008
    Nơi ở
    /media/Anime
    Bài viết
    2,288

    @minhphuong90 : Mình đã demo cho bạn rồi mà, bạn đọc chưa zậy ?

    Cách ở trên của mình là bỏ qua dòng n = 0, cách này là xóa code của dòng n = 0 :

    C++ Code:
    1. #include <stdio.h>
    2. #include <windows.h>
    3.  
    4. void test()
    5. {
    6.     long num = 0;
    7.     long *p = (&num) + 2;
    8.     char *p2 = (char *)(p[0]);
    9.  
    10.     DWORD OldProtect, NewProtect = PAGE_EXECUTE_READWRITE;
    11.  
    12.     VirtualProtect((LPVOID)p2,7,NewProtect,&OldProtect);
    13.    
    14.     for (int i=0;i<7;i++)
    15.         p2[i] = 0x90;
    16.  
    17.     VirtualProtect((LPVOID)p2,7,OldProtect,&NewProtect);
    18. }
    19.  
    20. int main()
    21. {
    22.     int n = 100;
    23.     test();
    24.     n = 0;
    25.     printf("n = %d\n", n);
    26.     return 0;
    27. }

    Còn đây là code dựa trên ý tưởng của RadicalLight :

    C++ Code:
    1. #include <stdio.h>
    2. #include <windows.h>
    3.  
    4. void test()
    5. {
    6.     long num = 0;
    7.     long *p = (&num) + 2;
    8.  
    9.     DWORD OldProtect, NewProtect = PAGE_EXECUTE_READWRITE;
    10.  
    11.     p = (long *)(p[0] + 3);
    12.  
    13.     VirtualProtect((LPVOID)p,7,NewProtect,&OldProtect);
    14.     p[0] = 100;
    15.     VirtualProtect((LPVOID)p,7,OldProtect,&NewProtect);
    16. }
    17.  
    18. int main()
    19. {
    20.     int n = 100;
    21.     test();
    22.     n = 0;
    23.     printf("n = %d\n", n);
    24.     return 0;
    25. }
    Đã được chỉnh sửa lần cuối bởi meoconlongvang : 27-01-2009 lúc 09:01 PM.
    Càng yêu mèo thì mèo càng mập. Mèo càng mập ta lại càng yêu.

  9. #9
    Ngày gia nhập
    11 2007
    Bài viết
    153

    C Code:
    1. void test()
    2. {
    3.     long num = 0;
    4.     long *p = (&num) + 2;
    5.     (*p) += 7;
    6. }

    Không hiểu chút nào cả ? Tại sao cái này lại bỏ qua dòng mà n=0 hả mèo ? Giải thích cho mình được không ?
    ttecak ?

  10. #10
    Ngày gia nhập
    02 2008
    Bài viết
    4

    Em hiểu thế này ko biết có đúng ko
    Với trình biên dịch VC++
    Khi gọi hàm test thì địa chỉ câu lệnh tiếp theo hàm test được đưa vào trong Stack . Ví dụ lúc này địa chỉ của của đỉnh ngăn xếp là X , và giá trị của bộ nhớ tại X là Y và Y là địa chỉ của câu lệnh tiếp theo hàm test . Giờ chỉ cần thay giá trị của ô nhớ có địa chỉ X chính là quyết định câu lệnh nào sẽ thực hiện sau khi xong hàm test
    khi vô hàm test thì
    giá trị của thanh ghi ebp cũng được đẩy vào stack lúc này giá trị của thanh ghi esp mang giá trị X - 4 vì khi đẩy vô STACK thì địa chỉ của đỉnh ngăn xếp giảm đi 4 Byte . sau đó thanh ghi ebp được gán giá trị của thanh ghi esp vì thế ebp mang giá trị = X - 4 sau đó khi khai báo biến num trong hàm test thì địa chỉ của biến num sẽ là giá trị của thanh ghi ebp - 4 byte . vậy địa chỉ của biến num là X - 8 . vì thế long *p = (&num) + 2; chính là cho con trỏ trỏ đến địa chỉ là X - 8 + 8 = X vì biến con trỏ p là kiểu long ( 4 byte ) nên + 2 sẽ thành 8 byte . Vì vậy p trỏ vào địa chỉ là X như thế chỉ cần thanh đổi giá trị vùng nhớ X và lúc đó *p = Y . Vậy *p +=7 chính là địa chỉ của câu lệnh printf . Cái + 7 thì là do n = 0 sinh ra mã asm mất 7 byte vì thế câu địa chỉ câu lệnh printf = địa chỉ câu lệnh "n = 0" + 7 .

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn