The assembler translates assembly instructions into machine instructions and stores them in the target file. Assembler directives are different from assembly instructions; they guide the assembler on how to define variables and functions, and how to store assembly instructions in the target file. Assembler directives instruct the assembler on its operation.
Use assembler directives such as the .data
subsection and the .text
subsection in the assembly source file to specify the data and code segments where the following statements are stored in the target file. When a more refined segment type needs to be specified, you can use the .section
name directive.
.data # Specify the data segment to store the next data in the target file
str:
.ascii "test\000"
var:
.word 10
.text # Specify the code snippet for storing the next data in the target file
add:
The assembler directive .set
symbol, expression is used for constant settings.
.set FLAG, 0
.equ FLAG, 0
In conjunction with constant settings, the assembler directives .if
, .else
, and .endif
can be used to achieve conditional compilation.
.set FLAG, 0
.LC0:
.ascii "test1\000"
.LC1:
.ascii "test2\000"
main:
addi.d $sp, $sp, -8
st.d $ra, $sp, 0
.if FLAG == 1
la.local $r4, .LC0
.else
la.local $r4, .LC1
.endif
bl %plt(puts)
For conditional compilation, preprocessing commands such as #ifdef
, #else
, and #endif
in the C language can also be used directly in the assembly source file. When using these C language preprocessing commands, the assembly source file cannot be compiled directly with the assembler; instead, it needs to be processed first using the compiler’s preprocessing tool to translate the preprocessing commands.
Command | Function |
---|---|
|
If the symbol symbol has already been defined, assemble the following code. |
|
If the symbol symbol has not been defined before, assemble the following code, which is equivalent to. ifnotdef symbol. |
|
If two strings are the same, assemble the following code, which is equivalent to .ifeqs str1, str2. |
|
If two strings are different, assemble the following code. |
|
If the expression value is 0, assemble the following code. |
|
If the expression value is greater than or equal to 0, assemble the following code. |
|
If the expression value is greater than 0, assemble the following code. |
|
If the expression value is less than or equal to 0, assemble the following code. |
|
If the expression value is less than 0, assemble the following code. |
The information output instructions that can be used during the assembly process of the assembler include:
-
.print
string
-
.fail
expression
-
.error
string &.err
An error or warning message will be generated. When the expression value is greater than or equal to 500, the assembler will output a warning message; if expression value is less than 500, the assembler will output an error message. The default value of expression is 0, and the .fail
parameter can be written directly and left blank.
There are two ways to reference other files in the assembly source file. One method is to use the assembler directive .include
'file
', which defaults to the current directory for the reference file path. If the referenced file is not in the same directory, the search path can be controlled through the compiler’s command-line option parameter '- I
'. The other method is to use the C language preprocessing command #include
, which requires the assembler file to have a .S
and to be preprocessed by the front-end preprocessing tool.
#ref.S
.text
test:
.print "test"
.jr $r1
#main.S
.include "ref.S"
The assembler directives .rept count
and .endr
can be used to loop through their internal statements count times.
.rept 3
nop
.endr
The above code is equivalent to instruct the assembler to generate three nop
instructions in the target file. When it is necessary to insert a different number of nop
instructions for address alignment based on the actual situation, using the loop unrolling directive is very convenient.
The assembler directives .irp symbol, values
and .endr
can also be used to loop through their internal statements.
.irp n,4,5,6,7,8,9,10,11,12
st.d $r\n, $sp, \n*8
.endr
is equivalent to :
st.d $r4, $sp, 0x20
st.d $r5, $sp, 0x28
st.d $r6, $sp, 0x30
st.d $r7, $sp, 0x38
st.d $r8, $sp, 0x40
st.d $r9, $sp, 0x48
st.d $r10, $sp, 0x50
st.d $r11, $sp, 0x58
st.d $r12, $sp, 0x60
The assembler directive .macro name args
functions similarly to the macro definition in the C language, where name
is the macro name, args
is the parameter, and ends with .endm
.
For example, here’s how you can implement a macro definition that generates a different number of nop
instructions based on different parameters:
.text
.macro INSERT_NOP a
.rept \a
nop
.endr
.endm
Here, .text
is used to indicate that the following instructions are stored in the code section of the target file. The macro name is INSERT_NOP
, and the parameter is a
. The format for using parameters in the macro definition body is "parameter", such as a
. The parameters of the macro can be 0 or multiple, with commas or spaces used to separate them when there are multiple parameters. When the program is in use, simply call the macro.
INSERT_NOP 3
INSERT_NOP 7
-
The registers in CFI do not use "
$r1
" or "r1
", they are represented only by their numbers, such as "1
" for "$r1
" .
In some cases, we may want to use different options only for certain assembly, so the .option
directive is added to control the assembler options.
Syntax:
.option option1 [, option2 , ...]
The .option
directive selects options for the assembler output listing. The options must be separated by commas; each option selects a listing feature. These are four valid options:
push limits the scope of the option change.
relax causes the R_LARCH_RELAX to be emitted.
norelax suppresses the R_LARCH_RELAX to be emitted.
pop limits the scope of the option change.
.option push
and .option pop
limit the scope of the option change, and other assembly will not be affected. Using .option pop
correctly restores all target features to their state at the point where .option pop
was last used. .option relax
causes R_LARCH_RELAX
to be emitted, and .option norelax
suppresses it.
Here is an example of le relax:
.text
L1:
.option push
.option norelax
lu12i.w $t0,%le_hi20(s)
addi.d $t0,$t0,le_lo12(s)
.option relax
lu12i.w $t0,%le_hi20(s)
addi.d $t0,$t0,le_lo12(s)
.option pop
After assembly:
Disassembly of section .text:
0000000000000000 <L1>:
0: 1400000c lu12i.w $t0, 0
0: R_LARCH_TLS_LE_HI20 s
4: 02c0018c addi.d $t0, $t0, 0
4: R_LARCH_TLS_LE_LO12 s
8: 1400000c lu12i.w $t0, 0
8: R_LARCH_TLS_LE_HI20 s
8: R_LARCH_RELAX *ABS*
c: 02c0018c addi.d $t0, $t0, 0
c: R_LARCH_TLS_LE_LO12 s
c: R_LARCH_RELAX *ABS*