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"
.
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