[英]A simple while-loop in GCC inline assembly
我想使用GCC擴展內聯ASM編寫以下循環:
long* arr = new long[ARR_LEN]();
long* act_ptr = arr;
long* end_ptr = arr + ARR_LEN;
while (act_ptr < end_ptr)
{
*act_ptr = SOME_VALUE;
act_ptr += STEP_SIZE;
}
delete[] arr;
分配長度為ARR_LEN
long
類型的數組,並將其初始化為零。 循環以STEP_SIZE
的增量STEP_SIZE
數組。 每個觸摸的元素都設置為SOME_VALUE
。
好吧,這是我第一次在GAS中嘗試:
long* arr = new long[ARR_LEN]();
asm volatile
(
"loop:"
"movl %[sval], (%[aptr]);"
"leal (%[aptr], %[incr], 4), %[aptr];"
"cmpl %[eptr], %[aptr];"
"jl loop;"
: // no output
: [aptr] "r" (arr),
[eptr] "r" (arr + ARR_LEN),
[incr] "r" (STEP_SIZE),
[sval] "i" (SOME_VALUE)
: "cc", "memory"
);
delete[] arr;
如注釋中所述,確實,此匯編代碼更像是do {...} while
循環,但實際上它執行相同的工作。
那段代碼的真正奇怪之處在於,一開始它對我來說效果很好。 但是當我后來試圖使其在另一個項目中工作時,似乎似乎什么也做不了。 我什至制作了工作項目的1:1副本,再次進行編譯,...結果仍然是隨機的。
也許我對輸入操作數使用了錯誤的約束,但是到目前為止,我實際上已經嘗試了幾乎所有輸入操作數,而且我還沒有真正的想法。 特別令我困惑的是,它在某些情況下仍然有效。
盡管我在上大學時就已經學過,但我並不是ASM的專家。 請注意,我不是在尋求優化-我只是想了解內聯匯編的工作方式。 所以這是我的問題:我的嘗試有根本性的錯誤嗎?還是我在這里犯了一個更細微的錯誤? 提前致謝。
(使用g ++ MinGW Win32 x86 v.4.8.1)
更新資料
到目前為止,我已經嘗試了所有在此提出的建議。 我特別嘗試過
... : [aptr] "=r" (arr) : "0" (arr) ...
相反,相同的結果, ... : [aptr] "+r" (arr) : ...
仍然相同。 同時,我非常了解官方文檔 ,但仍然看不到我的錯誤。
您正在修改不允許的輸入操作數( aptr
)。 約束它與輸出操作數匹配或將其更改為輸入/輸出操作數。
這是具有預期行為的完整代碼。
%%rbx
代替%%ebx
作為陣列的基地址。 出於相同的原因,應使用leaq
和cmpq
代替leal
和cmpl
。 long
應使用movq
。 long
類型是8字節而不是4字節。 jl
應該更改為jg
。 ebx
)替換它們。 不能使用約束"r"
。 "r"
表示可以使用任何寄存器,但是leaq
不能接受任何寄存器組合。 在這里看: x86尋址模式
#include <iostream> using namespace std; int main(){ int ARR_LEN=20; int STEP_SIZE=2; long SOME_VALUE=100; long* arr = new long[ARR_LEN]; int i; for (i=0; i<ARR_LEN; i++){ arr[i] = 0; } __asm__ __volatile__ ( "loop:" "movq %%rdx, (%%rbx);" "leaq (%%rbx, %%rcx, 8), %%rbx;" "cmpq %%rbx, %%rax;" "jg loop;" : // no output : "b" (arr), "a" (arr+ARR_LEN), "c" (STEP_SIZE), "d" (SOME_VALUE) : "cc", "memory" ); for (i=0; i<ARR_LEN; i++){ cout << "element " << i << " is " << arr[i] << endl; } delete[] arr; return 0; }
對於x86和x64都有效的答案如何(盡管它確實假設long始終為4字節,例如Windows)? OP的主要更改是使用“ + r”和(溫度)。
#include <iostream>
using namespace std;
int main(){
int ARR_LEN=20;
size_t STEP_SIZE=2;
long SOME_VALUE=100;
long* arr = new long[ARR_LEN];
for (int i=0; i<ARR_LEN; i++){
arr[i] = 0;
}
long* temp = arr;
asm volatile (
"loop:\n\t"
"movl %[sval], (%[aptr])\n\t"
"lea (%[aptr], %[incr], %c[size]), %[aptr]\n\t"
"cmp %[eptr], %[aptr]\n\t"
"jl loop\n\t"
: [aptr] "+r" (temp)
: [eptr] "r" (arr + ARR_LEN),
[incr] "r" (STEP_SIZE),
[sval] "i" (SOME_VALUE),
[size] "i" (sizeof(long))
: "cc", "memory"
);
for (int i=0; i<ARR_LEN; i++){
cout << "element " << i << " is " << arr[i] << endl;
}
delete[] arr;
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.