2011-08-21 29 views
5

Tôi đang cố gắng hiểu một số điều về trình tạo nội tuyến trong Linux. Tôi đang sử dụng chức năng sau:Nghi ngờ nội tuyến ASM

void test_func(Word32 *var){ 
    asm(" addl %0, %%eax" : : "m"(var)); 
    return; 
} 

nó tạo ra sau mã lắp ráp:

.globl test_func 
.type test_func, @function 
test_func: 
     pushl %ebp 
     movl %esp, %ebp 
#APP 
# 336 "opers.c" 1 
     addl 8(%ebp), %eax 
# 0 "" 2 
#NO_APP 
     popl %ebp 
     ret 
     .size test_func, .-test_func 

Nó tóm var địa chỉ mem để EAX đăng ký giá trị thay vì giá trị var.

Có cách nào để chỉ dẫn lệnh addl sử dụng giá trị var thay vì địa chỉ mem mem mà không sao chép địa chỉ var mem vào sổ đăng ký không?

Kính trọng

+0

asm inline của bạn không xác định những gì được cho là trong EAX, vì vậy gcc có thể đặt bất cứ điều gì có ... những gì là bạn thực sự cố gắng để làm gì? – servn

Trả lời

3

Nó tính tổng địa chỉ mem var vào giá trị đăng ký thay thế giá trị var thay thế.

Có, cú pháp của gcc inline assembly là khá phức tạp. Việc diễn giải từ phần có liên quan trong số GCC Inline Assembly HOWTO"m" gần cung cấp cho bạn vị trí bộ nhớ của biến C.

Đó là những gì bạn sẽ sử dụng khi bạn chỉ muốn một địa chỉ bạn có thể viết hoặc đọc từ đó. Chú ý Tôi đã nói vị trí của biến số C, do đó, %0 được đặt thành địa chỉ Word32 *var - bạn có con trỏ trỏ đến con trỏ. Bản dịch C của khối lắp ráp nội tuyến có thể trông giống như EAX += *(&var) vì bạn có thể nói rằng ràng buộc "m" ngầm định lấy địa chỉ của biến C và cung cấp cho bạn một biểu thức địa chỉ, sau đó bạn thêm vào %eax.

Có cách nào để chỉ dẫn lệnh addl sử dụng giá trị var thay vì địa chỉ mem mem mà không sao chép địa chỉ var mem vào sổ đăng ký không?

Điều đó tùy thuộc vào ý bạn. Bạn cần phải nhận được var từ ngăn xếp, vì vậy ai đó có bộ nhớ dereference (xem @Bo Perssons trả lời), nhưng bạn không phải làm điều đó trong lắp ráp nội tuyến

Ràng buộc cần phải là "m"(*var) (như @fazo đề xuất). Điều đó sẽ cung cấp cho bạn vị trí bộ nhớ của giá trị var trỏ đến, thay vì vị trí bộ nhớ trỏ đến nó.

Các mã được tạo bây giờ là:

test_func: 
    pushl %ebp 
    movl %esp, %ebp 
    movl 8(%ebp), %eax 
#APP 
# 2 "test.c" 1 
    addl (%eax), %eax 
# 0 "" 2 
#NO_APP 
    popl %ebp 
    ret 

Đó là một chút nghi ngờ, nhưng điều đó hoàn toàn dễ hiểu khi bạn quên nói với GCC mà bạn clobbered (sửa đổi mà không cần phải trong đầu vào danh sách/đầu ra) %eax. Sửa rằng asm("addl %0, %%eax" : : "m"(*var) : "%eax") tạo:

movl 8(%ebp), %edx 
    addl (%edx), %eax 

Mà không phải là bất kỳ tốt hơn hoặc nhiều hơn đúng trong trường hợp này, nhưng nó luôn luôn là một thực hành tốt để nhớ. Xem phần trên clobber list và đặc biệt chú ý đến kẹp giấy "memory" để sử dụng nâng cao lắp ráp nội tuyến.

Mặc dù bạn không muốn (rõ ràng) tải địa chỉ bộ nhớ vào sổ đăng ký, tôi sẽ trình bày ngắn gọn nó. Thay đổi chế "m"-"r" gần như có vẻ để làm việc, bộ phận có liên quan được thay đổi để (nếu chúng ta bao gồm %eax trong danh sách clobber):

movl 8(%ebp), %edx 
    addl %edx, %eax 

Đó là gần như chính xác, chúng tôi đã nạp giá trị con trỏ var vào một đăng ký, nhưng bây giờ chúng ta phải xác định chính mình rằng chúng ta đang tải từ bộ nhớ. Thay đổi mã để phù hợp với hạn chế (thường là không mong muốn, tôi chỉ thấy nó cho đầy đủ):

asm("addl (%0), %%eax" : : "r"(var) : "%eax"); 

Cung cấp:

movl 8(%ebp), %edx 
addl (%edx), %eax 

Giống như với "m".

3

có, bởi vì bạn cho anh ta var là địa chỉ. cho anh ta * var.

thích:

void test_func(Word32 *var){ 
    asm(" addl %0, %%eax" : : "m"(*var)); 
    return; 
} 

tôi không nhớ chính xác, nhưng bạn nên thay thế "m" với "r"?

toán hạng bộ nhớ không có nghĩa là nó sẽ lấy giá trị từ địa chỉ đó. nó chỉ là một con trỏ

+0

Làm điều đó nó sẽ ghi đè lên% eax giá trị với địa chỉ var để có được giá trị var. – LooPer

1

Không, không có chế độ địa chỉ cho bộ vi xử lý x86 đi hai cấp gián tiếp.

Trước tiên, bạn phải tải con trỏ từ địa chỉ bộ nhớ và sau đó tải gián tiếp từ con trỏ.

0

Hãy thử

void test_func(Word32 *var){ 
    asm(" mov %0, %%edx; \ 
    addl (%%edx), %%eax" : : "m"(var));  

    return; 
} 
Các vấn đề liên quan