Chuyển Assembly sang C Code và cách hoạt động của Memory

Em chào mọi người,

Không biết có anh/chị nào học về phần liên quan đến kiểu Assembly, hay dạng như lý thuyết về cách hoạt động của Stack có thể giúp em 1 tí được không ạ?
Đầu tiên là về phần xác định địa chỉ.
Đáp án của em lần lượt là 968/968/972/976/980/964 (Này là đáp án em và bạn cùng thảo luận).
Tuy nhiên em thấy hơi sai vì như lý thuyết em được học thì location sẽ theo kiểu %ebp + 4
Tức là

  • old ebp: ebp
  • return address : 4(ebp)
  • parameter 1: 8(ebp)
  • parameter n: 4n + 4(ebp)

Câu tiếp theo em muốn hỏi là việc chuyển đổi từ Assembly sang C code, em có thực hiện như sau

int func(int x, inty)
{
    int result = 0;
    int check = 0;
    while(check < y)
    {
        result += (x + 4 * check);
        check++;
    }
    return result;
}

Em cảm ơn nhiều ạ

1 Like

Mặc dù đáp án bạn em chỉ là như vậy, nhưng khi dựa vào cái này thì em lại thấy không đúng.
Vì return address phải lớn hơn ebp, còn local variable như t đáng lẽ phải là -4(%ebp) :frowning:

Đây là đáp án của mình:

Ref link: https://inst.eecs.berkeley.edu/~cs161/sp16/slides/buffer%20overrun.pdf

4 Likes

Em cảm ơn anh nhiều ạ.
Trong lúc em chờ mọi người giải đáp thì có 1 anh khóa trên giảng và em làm lại như sau.
Anh nói em khi muốn tìm địa chỉ này thì cứ xét trên parameter xa nhất.
Nên kiểu em tính được là

  • y = 960
  • x = 956
  • return: 952
  • ebp: 948
  • local t: 944
  • esp: 944
    Nếu như em áp kết quả của em vào cái bảng dưới này thì em thấy hợp lí. Không biết anh thấy em có hiểu sai ở đâu không.
    Nếu như cách giải của anh thì theo em hiểu là esp contain 960 phải giảm đi 8 để có giá trị ebp ban đầu.
    Từ ebp (952) thì em có thể tự suy ra return value. Từ return value + 4 là ra para 1, para 2 là cộng thêm 4.
    Location thì -4(%ebp) cũng đúng như KQ của anh luôn.

Nên em không biết nếu như anh kia chỉ em thì ảnh đã nhầm ở đâu không ạ :3
Vì thực ra em chỉ bị cấn chỗ tìm ra được ebp thì có thể dễ dàng biết mấy cái còn lại.
esp theo em biết thì nó sẽ ở cùng vị trí với cái local variable, trong trường hợp không có local var thì nó sẽ cùng vị trí ebp.

Mấu chốt của đề là thời điểm đang xét giá trị của esp.
Như đề bảo là immediately before the instruction call func, nghĩa là lúc này đã push parameters lên stack rồi.

Bạn tham khảo trong link mình gửi:

2 Likes

Dạ em cảm ơn nhiều ạ.
Có gì để em check lại rồi confirm với anh ^^

Theo trang 6 của cái PDF anh gửi cho em thì em thấy đáp án em sao có vẻ hợp lí
Như khi em đọc thì ngay trước khi call foo, esp đang trỏ tới một local của main
“Arguments pushed on stack in reverse order (last argument pushed first)”
Có phải y không thể nằm cao hơn địa chỉ hiện tại mà esp trỏ đến bởi vì esp thuộc về hàm func mà trước khi gọi hàm func esp đang ở 960 thì khi gọi hàm func esp lại không thể chạy ngược lên 964 được (?)
Có gì anh thấy em hiểu sai ở đâu không

  1. Bạn chú ý đừng nhầm lẫn chiều của stack nhé. Chiều của stack trong hình vẽ của bạn là từ thấp lên cao, trong khi chiều của stack trong file PDF là từ cao xuống thấp. Khi phân tích dễ bị nhầm nếu không lưu ý chuyện đó.
  2. Việc thực hiện gọi hàm foo() sẽ có 2 bước.
  • Bước 1: Push các parameters của hàm foo() vào stack theo thứ tự. Như ở ví dụ là foo(1,2,3) sẽ push là 3, 2, 1. Việc này sẽ tăng stack size lên, cụ thể là esp sẽ GIẢM thêm 3*4 bytes cho 3 biến int.
  • Bước 2: thực hiện instruction call foo.
    Tổng hợp 2 bước này trong C thì chỉ là 1 hàm foo(), nhưng do ở ASM nó tách thành 2 giai đoạn, mà theo như đề của bạn thì "immediately before the instruction call func" nên mình cho rằng esp đã được tăng lên 4*2 byte cho việc 2 biến x, y đã lên stack. Nó là call func chứ không phải call func().

Như vậy tại thời điểm esp contains 960, nó đang trỏ tới biến x.

Ngoài lề: Thực tế trên các compiler, thứ tự vị trí các biến local trong foo() sẽ không đúng như bài giảng mà bạn học. Các compiler sẽ tự quyết định xem đặt biến theo thứ tự nào là hợp lý và tối ưu với nó. Thường thì chuyện này chỉ xuất hiện khi các biến có kiểu dữ liệu khác nhau. Ví dụ:

void foo() {
 char a;
 int b;
 char c[3];
}

Compiler có thể tráo biến b và a để giảm stack size.

3 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?