Linux C language inline assembly

Source: Internet
Author: User

Recently, a key part of the C language algorithm needs to be implemented in assembly language. In Linux, AT&T assembly is basically used for Embedded Assembly. For example, AT&T assembly is used for Linux system startup. I have studied AT&T assembly before, but I have forgotten it after a while, but I am familiar with Intel assembly basics. The two are basically similar in usage, so I am familiar with Intel assembly, it's easy to spend some time reading AT&T's compilation.
Next, let's take a look at the differences between the two and give a specific example of embedding AT&T assembly in the Linux language.
I. Differences between AT&T assembly and Intel assembly
1. The order of source and destination operands is the opposite. The source and purpose of AT&T are from left to right, and "%" must be added before its register; Intel is from right to left, and "%" is not required ".
Example: AT&T: movl % ecx, % eax (ecx is the source operand, eax is the destination operand)
Intel: mov dx, bx (bx is the source operand, dx is the destination operand
2. AT&T needs to add "$" before the immediate operand; Intel does not need it.
Example: AT&T: movl $2, % eax
Intel: mov ax, 2
3. The length of memory operations in AT&T is determined by the last character of the operating code. "B", "w", "l", respectively, indicates that the memory reference is 1-byte 8-bit, 2-byte 16-bit, and 4-byte 32-bit.
Intel uses the operation prefix byte ptr, word ptr, and dword ptr.
Example: AT&T: movl % ecx, % eax
Intel: mov al, byte ptr ttt

These three points are the most important differences. In addition, the jump/call time is not the same.

Ii. Embedded Assembly basic format

Asm ("Assembly Statement"
"Output register"
"Input register"
"The modified register" // tells the compiler that the specified register must be rewritten when the _ asm _ statement is executed, therefore, do not use the register here to save other values during this period.
)
 
// Asm. c
# Include <stdio. h>

Unsigned int LeftShift (unsigned int uiNumber, unsigned char iBits)
{
Register unsigned int _ res;
_ Asm _ ("rol % 1, % eax ;"
: "= A" (_ res)
: "C" (iBits), "0" (uiNumber)
);
 
Return _ res;
}

Int main (void)
{
Unsigned int ret = 0;
 
Ret = LeftShift (4, 2 );
Printf ("1, ret: % u \ n", ret );
 
Return 0;
}

[Root @ xxx asm_study] # gcc asm. c-o app
[Root @ xxx asm_study] #./app
1, ret: 16

The preceding example shows the Left shift of a loop. Instead of focusing on the Left shift of the loop, it refers to the rol itself and only the AT&T Assembly usage.
First, a register Variable _ res is defined to save the return value.
AT&T Assembly uses registers, which must be preceded by "%". In C, "%" is a special format character, therefore, two percent signs "%" are required to finally represent a "%", which is a bit similar to the escape character.
: "= A" (_ res) indicates that the value of register eax is output to _ res, and % 0 indicates this register,
: "C" (iBits), "0" (uiNumber), c indicates the input sender ecx, 0 indicates that the above output register eax is used, therefore, ecx and eax respectively Save the iBits and uiNumber variable values. In the instruction, % 1 refers to the Register ecx, so its numbering rules start from "output sender" from left to right, from top to bottom.
It can be found that rol % 1, % eax can be directly written as: rol % 1, % 0

C language version shifts left
A c language version is provided to move the code left by loop. If you are interested, you can compare it with the assembly version above.
// Ori. c
Unsigned int LeftShift2 (unsigned int uiNumber, unsigned char iBits)
{
Int I = 0;
Unsigned int iret = uiNumber;
Unsigned int iR = 0x01;
 
For (I = 0; I <iBits; I ++)
{
IR = iret & 0x80000000;
Iret = iret <1;
IR = iR> 31;
Iret = iret | iR;
}
 
Return iret;
}
Int main (void)
{
Unsigned int ret = 0;
 
Ret = LeftShift2 (4, 2 );
Printf ("2, ret: % u \ n", ret );
 
Return 0;
}
[Root @ xxx asm_study] # gcc ori. c-o app
[Root @ xxx asm_study] #./app
2, ret: 16

Iv. macro definition version Compilation
# Define LeftShift (uiNumber, iBits )\
({\
Register unsigned int _ res ;\
_ Asm _ ("rol % cl, % eax ;"\
: "= A" (_ res )\
: "C" (iBits), "a" (uiNumber ));\
_ Res ;})
The difference from a normal assembly is that "\" must be added after each line, and the return value is written to the end, as shown in the last _ res above.

V. c program is transformed into assembler program
1. Convert *. c program into AT&T format Assembly *. s
[Root @ xxx asm_study] # gcc-S asm. c-o asm. s
[Root @ xxx asm_study] # ls-al asm. s
-Rw-r -- 1 root 1387 06-30 10:41 asm. s
 
2. Convert *. c program into Intel format Assembly *. s
[Root @ xxx asm_study] # gcc-masm = intel test. c-o test. s
Of course, if you want to convert a c program into an Intel assembly, it cannot contain an assembly in AT&T format; otherwise, it cannot be transferred.
By rosetta
 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.