日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

stol函数在linux下使用,Linux下ATT汇编语法简介一

發布時間:2025/3/15 linux 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 stol函数在linux下使用,Linux下ATT汇编语法简介一 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這顯得很古怪,不過在gcc知道程序員拿這些寄存器做些什么后,這確實能夠對gcc的優化操作有所幫助。表5-3中是一些可能會用到的寄存器加載代碼及其具體的含義。

表5-3 常用寄存器加載代碼說明

代 碼

說 明

代 碼

說 明

a

使用寄存器eax

m

使用內存地址

b

使用寄存器ebx

o

使用內存地址并可以加偏移值

c

使用寄存器ecx

I

使用常數0~31

d

使用寄存器edx

J

使用常數0~62

S

使用esi

K

使用常數0~255

D

使用edi

L

使用常數0~65535

q

使用動態分配字節可尋址機寄存器(eax、ebx、ecx、或edx)

M

使用常數0~3

r

使用任意動態分配的寄存器

N

使用1字節常數

g

使用通用有效的地址即可(eax、ebx、ecx、edx或內存變量)

O

使用常數0~31

A

使用eax與edx聯合(64位)

下面的例子不是讓程序員自己指定哪個變量使用哪個寄存器,而是讓gcc為程序員選擇。

01?asm("leal (%1, %1, 4),

%0"02?: " =r"(y)03?: "0"(x));

第一句匯編語句leal(r1,r2,4),r3語句表示r1+r2*4→r3,。這個例子可以非常快地將x乘5。其中“%0”,“%1”是指gcc自動分配的寄存器。這里“%1”代表輸入值x要放入的寄存器,“%0”表示輸出值寄存器。輸出寄存器代碼前一定要加入等于號。如果輸入寄存器的代碼時0或為空時,則說明使用與相應輸出一樣的寄存器。所以。如果gcc將r指定為eax的話,那么上面匯編語句的含義即為:“leal(eax,eax,4),eax”。

注意:在執行代碼時,如果不希望匯編語句被gcc優化而改變位置,就需要在asm符號后面添加volatile關鍵詞:asm

volatile(……);

或者更詳細地說明為:_

_asm_ _ _ _volatile_ _(……);

一、AT&T 格式Linux 匯編語法格式

1.在 AT&T

匯編格式中,寄存器名要加上 '%' 作為前綴;而在 Intel 匯編格式中,寄存器名不需要加前綴。?AT&T

格式

Intel

格式

pushl �x

push eax

2.在 AT&T 匯編格式中,用 '$' 前綴表示一個立即操作數;而在 Intel

匯編格式中,立即數的表示不用帶任何前綴。例如:

AT&T

格式

Intel

格式

pushl $1

push 1

AT&T 和 Intel

格式中的源操作數和目標操作數的位置正好相反。在 Intel 匯編格式中,目標操作數在源操作數的左邊;而在

AT&T 匯編格式中,目標操作數在源操作數的右邊。例如:

AT&T

格式

Intel

格式

addl $1, �x

add eax, 1

在 AT&T

匯編格式中,操作數的字長由操作符的最后一個字母決定,后綴'b'、'w'、'l'分別表示操作數為字節(byte,8

比特)、字(word,16 比特)和長字(long,32比特);而在 Intel 匯編格式中,操作數的字長是用 "byte ptr"

和 "word ptr" 等前綴來表示的。例如:

AT&T

格式

Intel

格式

movb val, %al

mov al, byte ptr val

5.在 AT&T

匯編格式中,絕對轉移和調用指令(jump/call)的操作數前要加上'*'作為前綴,而在 Intel 格式中則不需要。

遠程轉移指令和遠程子調用指令的操作碼,在

AT&T 匯編格式中為 "ljump" 和 "lcall",而在 Intel 匯編格式中則為 "jmp

far" 和 "call far",即:

AT&T

格式

Intel

格式

ljump $section, $offset

jmp far section:offset

lcall $section, $offset

call far section:offset

與之相應的遠程返回指令則為:

AT&T

格式

Intel

格式

lret $stack_adjust

ret far stack_adjust

在 AT&T 匯編格式中,內存操作數的尋址方式是

section:disp(base, index, scale)

而在 Intel 匯編格式中,內存操作數的尋址方式為:

section:[base + index*scale + disp]

由于 Linux 工作在保護模式下,用的是 32

位線性地址,所以在計算地址時不用考慮段基址和偏移量,而是采用如下的地址計算方法:

disp + base + index * scale

下面是一些內存操作數的例子:

AT&T

格式

Intel

格式

movl -4(�p), �x

mov eax, [ebp - 4]

movl array(, �x, 4), �x

mov eax, [eax*4 + array]

movw array(�x, �x, 4), %cx

mov cx, [ebx + 4*eax + array]

movb $4, %fs:(�x)

mov fs:eax, 4

linux內核嵌入式匯編總結(1)

在linux內核中有很多的嵌入式匯編代碼。

嵌入匯編的基本格式為:

asm("匯編語句":輸出寄存器:輸入寄存器 :會被修改的寄存器);

其中”匯編語句”是程序員寫匯編指令的地方;”輸出寄存器”表示當這段嵌入式匯編執行之后,哪些寄存器用于存放輸出數據。這些寄存器會分別對應一個C語言表達式或一個內存地址;“輸入寄存器”表示在開始執行匯編代碼時,這里指定的一些寄存器中應存放的輸入值,它們也分別對應著一個C變量或常數值。下面用例子來說明嵌入式匯編語句的使用方法。

我們在下面列出了一段代碼作為例子來詳細解說,

01?#define get_seg_byte(seg,addr)

\?02?({

\?03?register char __res;

\?04?__asm__("push %%fs;

\?05?mov %%ax, %%fs;

\?06?movb %%fs: %2, %%al;

\?07?pop %%fs"

\?08?:" =a" (__res)

\?09?:"" (seg),"m" (* (addr)));

\?10?__res; })

這段10行代碼定義了一個嵌入式匯編語言宏函數。通常使用匯編語句最方便的方式是把它們放在一個宏內。用圓括號括住的組合語句(花括號中的語句)可以作為表達式使用,其中最后的變量__res(第10行)是該表達式的輸出值。

因為是宏語句,需要在一行上定義,因此這里使用反斜杠'\'將這些語句連成一行。這條宏定義將被替換到宏名稱在程序中被引用的地方。第1行定義了宏的名稱,也就是宏函數名稱get_seg_byte(seg,addr)。第3行定義了一個寄存器變量_

_res。第4行上的_ _asm_

_表示嵌入式語句的開始。從第4行到第7行的4條AT&T格式的匯編語句。?第8行是輸出寄存器,這句的含義是在這段代碼運行結束后將eax所代表的寄存器的值放入_

_res變量中,作為本函數的輸出值,“=a”中的“a”稱為加載代碼,“=”表示這是輸出寄存器。第9行表示在這段代碼開始運行時將seg放到eax寄存器中,“”表示使用與上面同個位置的輸出相同的寄存器。而(*(addr))表示一個內存偏移地址值。為了在上面匯編語句中使用該地址值,嵌入式匯編程序規定把輸入和輸出寄存器統一按順序編號,順序是從輸出寄存器序列從左到右從上到下以“%0”開始,分別記為%0、%1、……%9。因此,輸出寄存器的編號是%0(這里只有一個輸出寄存器),輸出寄存器前一部分(””(seg))的編號是%1,而后部分的編號是%2。上面第6行上的%2即代表(*(addr))這個內存偏移量。

現在我們來研究4~7行上的代碼的作用。第一句將fs段寄存器的內容入棧;第二句將eax中的段值賦給fs段寄存器;第三句是fs:(*(addr))所指定的字節放入al寄存器中。當執行完匯編語句后,輸出寄存器eax的值將被放入_

_res,作為該宏函數的返回值。

01?asm("cld\n\t"02?"rep\n\t"03?"stol"04?:

05?:

"c"(count-1), "a"(file_value),

"D"(dest)06?:

"�x", "�i");

1~3行這三句是通常的匯編語句,用以清方向位,重復保存值。第4行說明這段嵌入匯編程序沒有用到輸出寄存器。第5行的含義是:將count-1的值加載到ecx中,dest放到edi中。為什么要讓gcc編譯程序去做這樣的寄存器值的加載,而不讓我們自己做呢?因為gcc在它進行寄存器分配時可以進行某些優化工作。例如fill_value值可能已經在eax中。如果是在一個循環語句中的話,gcc就可能在整個循環操作中保留eax,這樣就可以在每次循環中少用一個movel語句。最后一行的作用是告訴gcc這些寄存器中的值已經改變了。

通過上面分析,我們知道,宏名稱中的seg代表一指定的內存段值,而addr表示一內存偏移地址量。到現在為止,我們應該很清楚這段程序的功能了吧!該宏函數的功能是從指定段和偏移值的內存地址處取一個字節。再看下一個例子。

總結

以上是生活随笔為你收集整理的stol函数在linux下使用,Linux下ATT汇编语法简介一的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。