GCC uses AT & T's assembly format

xiaoxiao2021-03-06  46

The GCC uses the assembly format of AT & T, and MS uses Intel's format.

A basic syntax

The following is mainly different in the grammar.

★ Register naming principle

AT & T:% EAX Intel: EAX

★ Source / destination operation order

AT & T: MOVL% EAX,% EBX Intel: MOV EBX, EAX

★ constant / immediate format

AT & T: MOVL $ _VALUE,% EBX Intel: Mov Eax, _Value

Put the address of _value into the EAX register

AT & T: MOVL $ 0xD00D,% EBX Intel: MOV EBX, 0xD00D

★ Operation length logo

AT & T: MOVW% AX,% BX Intel: MOV BX, AX

★ Addressing method

AT & T: IMMED32 (Basepointer, IndexPointer, Indexscale)

Intel: [Basepointer IndexPointer * IndexScale IMM32)

Linux works in the protection mode, uses a 32-bit linear address, so when the address is calculated

No need to consider the problem of segment: offset. The address in the above formula should be:

IMM32 Basepointer IndexPointer * IndexScale

Here are some examples:

★ Direct addressing

AT & T: _BOOGA; _BOOGA is a global C variable

Note Plus $ is an address reference, it is not added to indicate a value reference.

Note: For local variables, you can reference the stack pointer.

Intel: [_booga]

★ Indirect addressing of registers

AT & T: (% EAX)

Intel: [EAX]

★ Resident Address

AT & T: _VARIABLE (% EAX)

Intel: [EAX _VARIABLE]

AT & T: _Array (,% EAX, 4)

Intel: [EAX * 4 _Array]

AT & T: _Array (% EBX,% EAX, 8)

Intel: [EBX EAX * 8 _Array]

Two basic line compilation

The basic line of compilation is simple, usually in accordance with the format below

ASM ("Statements");

For example: ASM ("NOP"); ASM ("CLI");

ASM and __ASM__ are exactly the same.

If there are multi-line compilation, you should add "/ n / t" every line.

E.g:

ASM ("Pushl% EAX / N / T"

"MOVL $ 0,% EAX / N / T"

"POPL% EAX");

In fact, GCC is handling compilation, it is necessary to "print" to assembly.

In the file, the format control character is necessary.

Another example:

ASM ("MOVL% EAX,% EBX");

ASM ("XORL% EBX,% EDX");

ASM ("MOVL $ 0, _booga);

In the above example, since we have changed the value of EDX and EBX in the compilation of EDX and EBX,

Due to the special processing method of GCC, first form assembly files, then hand it over to GAS to compile,

So GAS doesn't know that we have changed the value of EDX and EBX, if the program's context

EDX or EBX is required to temporarily store, which will cause serious consequences. For variables _BOOGA also

There is the same problem. In order to solve this problem, it is necessary to use the expanded line compilation syntax. Three expansion

Extended line compilation is similar to Watcom.

The basic format is:

ASM ("Statements": Output_Regs: Input_regs: Clobbered_Regs;

Clobbered_Regs refers to a changed register.

Here is an example (see global variables for convenience):

INT count = 1;

INT value = 1;

Int buf [10];

void main ()

{

ASM (

"CLD / N / T"

"REP / N / T"

"stoSL"

:

: "C" (count), "Value)," D "(BUF [0])

: "% ECX", "% EDI");

}

The main assembly code obtained is:

Movl Count,% ECX

Movl value,% EAX

MOVL BUF,% EDI

#App

CLD

REP

StoSL

#NO_APP

CLD, REP, STOS will not be used more.

The functionality of these statements is to write a count Value value to BUF.

The statement after the colon indicates the input, output, and the changed register.

Through the statement after the colon, the compiler knows that your instruction needs and changes which registers,

Thereby, the allocation of the register can be optimized.

The symbol "C" (count) indicates that the value of count is put in the ECX register.

Similar to:

a eax

B EBX

C ECX

D Edx

S ESI

D Edi

I constant value, (0 - 31)

Q, R dynamically allocated register

g EAX, EBX, ECX, EDX or memory variable

A synthesize EAX and EDX a 64-bit register (Use long longs)

We can also let GCC choose the appropriate registers yourself.

Such as follows:

ASM ("LEAL (% 1,% 1, 4),% 0"

: "= r" (x)

: "0" (x));

This code implements a fast multiplication of 5 * x.

The main assembly code obtained is:

MOVL X,% EAX

#App

Leal (% EAX,% EAX, 4),% EAX

#NO_APP

MOVL% EAX, X

Some explanations:

1. Use Q to indicate the compiler from EAX, EBX, ECX, and EDX allocation registers.

Use R to indicate the compiler from EAX, EBX, ECX, EDX, ESI, EDI allocation registers.

2. We don't have to put the registers allocated by the compiler into the list of changed registers because the register

I have remembered them.

3. "=" is labeled the output register and must be used.

4. Digital% N usage:

The number representation of the number is to map to "R" or "Q" in order to appear and from left to right.

Register. If we want to reuse the registers requested by "R" or "Q", you can use them.

5. If you enforce the fixed register, if you do not need% 1, use EBX,

ASM ("LEAL (%% EBX, %% EBX, 4),% 0"

: "= r" (x)

: "0" (x));

Be careful to use two% because a% of the syntax has been used by% N.

Below you can explain the problem with Letter 4854-4855:

1. Is there any special meaning of variables and double downline? Undering a crosline refers to global variables, but it doesn't matter if I am adding in my GCC.

2, what does the above definition will use the following call?

#define _syscall1 (Type, Name, Type1, Arg1) /

TYPE NAME (Type1 Arg1) /

{/

Long __res; /

/ * __RES should be a global variable * /

__ASM__ Volatile ("INT $ 0x80" /

/ * Volatile means not allowing optimization, so that the compiler strictly follows your assembly code * /

: "= a" (__res) /

/ * Generate code MOVL% EAX, __RES * /

: "0" (__nr _ ## name), "B" ((long))); /

/ * If I have not remembered, here ## refers to two macros.

That is, use the actual system call name instead "name", then unfold __nr _....

Then put the unfolded constant into EAX, put Arg1 in EBX * /

IF (__res> = 0) /

Return (Type) __res; /

Errno = -__ res; /

Return -1; /

}

转载请注明原文地址:https://www.9cbs.com/read-80646.html

New Post(0)