AT&T 汇编学习笔记

时间:2022-06-14 13:44:59
 汇编源文件为 cpuid.s

             1.编译:as 为gnu的编译器,ld为链接器。

           as  -o  cpuid.o cpuid.s
ld -o cpuid cpuid.o

             2.Using gdb:必须添加 -gstabs 参数

         

           as -gstabs -o cpuid.o cpuid.s
ld -o cpuid cpuid.o

             3.gdb 常用命令:

                        

                info registers          显示所有registers值
print/d/t/x to display the value in decimal/binary/hexadecimal
print $寄存器 打印寄存器的值
x/nyz 地址 打印指定地址的值
n is the number of fields to display
y is the format of the output
c for character
d for decimal
x for hexadecimal
z is the size of the field to be displayed
b for byte
h for 16-bit word
w for 32-bit word
example:
x/42cb &output

               4.The data section

               1>数据类型:

               

AT&T 汇编学习笔记

                  2>static symbols

                       .equ  前缀可以定义静态变量,eg.  .equ  factor, 3

                       如果想引用静态变量,则变量名前必须加“$”,eg.movl $LINUX  ,  %eax

              5.the  bss section

                  定义bss段的元素不同于data段,必须声明内存来存放内容。

             

.comm      declares a common memory area for data that is not initialized
.lcomm declares a local common memory area for data that is not initialized

  .comm   symbol, length

   symbol is a label assigned to the memory area,length is the number of bytes  contained in the memory area,eg.

          .section  .bss

          .lcomm  buffer,10000

           .lcomm  不能用于他们的声明函数外,不能在.global  指令内使用。

           将数据放在bss段有一个好处,数据不被包括在可执行文件中。当数据被定义在data段时,它必须被包括在可执行文件中,因为数据必须被赋值。正是由于bss中声明的数据不是被程序数据初始化的,内存空间在运行时被保留,不用必须包括在程序中。

 

              6.Moving  data

               movx   source,destination,注意,源数据和目的地址的顺序和intel的正好相反。

                                 x can be:           

                       l    32-bit long word
w 16-bit word
b 8-bit byte

 

              movl   $0 , %eax
              movl %eax , %ebx
              movb %al, %bx 错误,将8位的al中的数移动到bx的低八位,必
         须将ax内容整个移动到bx中,使用movw指令。
              movl value ,%eax value 内存标记
              movl %eax , value 寄存器中的变量移入内存

 

 

The CMOV instructions
cmovx source, destination
the conditions are based on the current values in the EFLAGS register.


Exchanging Data
xchg
xchg operand1,operand2 op can be register or memory location(but both cannot be a memory location)

bswap reverse the order of the bytes in a register .The bits are not reversed,the individual bytes contained within the register are reversed.大小端转换。

xadd the xadd instruction is to exchange the values between two registers,or a memory location and a register,add the values,and then store them in the destination location.

xadd source , destination

cmpxchg compares the destination with the value in the eax,ax or al registers.if equal,the source value is loaded into the destination;if not,destination value is loaded into the reginsters.

cmpxchg source,destination

cmpxchg8b works with 8-byte values,cmp the value in destination with the value in the edx and eax,edx being the high-order,if equal the ecx:ebx pair is moved to the destination;if not,the
value in the destination m emory address is loaded in the edx:eax pair.
cmpxchg8b destination

 

The stack
ESP register contains the memory address of the start of the stack.

PUSHint and POPing data
pushx/popx source
only 16 and 32-bit data values are allowed to be push'd.
l for a long word(32 bits)
w for a word(16 bits)


Controlling Execution Flow

Unconditional Branches

jumps
jmp location location is the memory address to jump to.

call address it remembers where it jumped from and has the capability to return there if needed.This is used when implementing functions.
a standatd template to use for function calls:

function_label:
pushl %ebp
movl %esp, %ebp
<normal function code goes here>
movl %ebp, %esp
popl %ebp
ret

Conditional Branches

The compare instruction
cmp operand1,operand2 it performs a subtraction operation on the two operands( operand2-operand1).Neither of the operands is modified,but the EFLAGS register is set.

Examples of using the flag bits
Using the Zero flag(zf)
je and jz instructions both branch if the Zero flag is set.The zf can be set by a CMP or a mathematical instruction that evaluates to Zero.
eg.
movl $10, %edi
loop1:
<other code instructions>
dec %edi
jz out
jmp loopl
out:

Using the overflow flag
working with signed numbers.It is set when a signed value is too large for the data element containing it.eg.

movl $1,%eax
movb $0x7f,%bl
addb $10,%bl
jo overhere
int $0x80
overhere:
movl $0,%ebx
int $0x80

 

Using the parity flag
The parity flag indicates the number of bits that should be one in a mathematical answer.This can be used as a crude error-checking system .
If the number of bits set to one in the resultant is even,the parity bit is set(one),on the other side,zero.eg.
.section .text
.globl _start
_start:
movl $1,%eax
movl $4,%ebx
subl $3,%ebx
jp overhere
int $0x80
overhere:
movl $100,%ebx
int $0x80


using the sign flag
The sign flag is used in signed numbers to indicate a sign change in the value contained in the register.In a signed number,the last(highest order) bit is used
as the sign bit.It indicates whether the numeric representation is negative(set to 1) or positive(set to 0).


using the carry flag
unsigned number 溢出的时候carry flag被设置为1.DEC and INC 不会改变cf位。如果unsigned 值小于0,cf位也会被设置。

以下指令可以显式修改carry 位:
CLC set it to zero
CMC change it to the opposite
STC set it to one


LOOPS
The loop instructions use the ECX register as a counter and automatically decrease its value.

LOOP Loop until the ECX register is zero
LOOPE/LOOPZ Loop until either the ECX register is zero,or the ZF flag is not set.
LOOPNE/LOOPNZ Loop until either the ECX register is zero,or the ZF flag is set.

loop address
address is a label name for a location in the program code to jump to.Unfortunately,the loop instructions support only an 8-bit offset
so only short jumps can be performed.eg.

<code before the loop>
movl $100,%ecx
loop1:
<code to loop throuth>
loop loopl
<code after the loop>

 

Rules for branch prediction

Backward branches are assumed to be taken;
Forward branches are assumed to be not taken;
Branches that have been previously taken are taken again.


Optimizing tips


1.Eliminate branches

2.Code predictable branches first

3.Unroll loops

 

Using Numbers

Extending integers

extending unsigned integers
movw %ax,%bx 不能保证ebx的高位为0,所以必须这么写:
movl $0,%ebx
movw %ax,%ebx


movzx source,destination 可以解决这个问题,将低位值拷入,并将高位清零。

extending singed intergers
movsx 功能基本同movzx,不过它保留符号位。

Defining inters in GAS
.quad 可以指定64位数
在gdb中,要用x/gd才能正确打印出.quad值。

 

SIMD Integers
64-bit packed byte integers
64-bit packed word integers
64-bit packed doubleword integers

movq
movq source,destination source and destination can be an MMX register(eg.mm0,mm1) ,an SSE register,or a 64-bit memorylocation.

SSE integers
128-bit packed byte integers
128-bit packed word integers
128-bit packed doubleword integers
128-bit packed quadword integers

Moving SSE integers
movdqa/movdqu source,destination "a","u",a for aligned,u for not. 移入xmm register.

 


Moving floating-point values

fld source source 32位,64位或者80位内存空间。fld指令将浮点数载入或者移出FPU寄存器。flds用来针对单精度浮点数,fldl用于双精度浮点数。fst用来读取fpu寄存器的栈顶
并且将值存入内存。对单精度是fsts,双精度fstl。


Moving SSE floating-point values pdf 222

 

Basic Math Functions

Addition

add source ,destination 可以使值,寄存器,或者内存,但是不能同时是内存空间。相加结果放入destination中。

Detecting a carry or overflow condition
如果进位或者溢出,EFLAGS 寄存器中的溢出进位标记和溢出标记会被设置,可以根据这个控制程序。


The ADC instruction
adc source , destination adc 指令会考虑到进位标记中的值,可以把两个超过add范围的值拆分,用adc进行相加。eg.pdf 240

Subtraction
sub source,destination
当无符号整型相减出现负值,可以用carry标记位来辨别。
sbb指令类似于adc指令,见p246

Incrementing and decrementing
INC and DEC 用来对无符号整型操作,不会影响carry 标记。

Multiplication

mul source 目标隐含,用于无符号整形。有符号的乘法运算用imul指令。这块比较复杂,见pdf251.

detecting overflows
可以用jo指令来跳转,jo检查carry位,如果发生改变则跳转。

Division
div divisor 用于无符号整数,divisor 是除数,被除数必须被存放在ax(16位)或者dx:ax(32位),或者edx:eax(64位)寄存器对中。
结果的整数部分放在eax中,余数放在edx(依次类推)中。

idiv divisor 用于有符号整数。


Shift Instructions
SAL 算数左移
SHL 逻辑左移

sal destination 左移一位
sal %cl,destination 左移%cl 位
sal shifter, destination 左移shifter 位

被移出的位会放入carry标记中。

 

shr 对无符号整型有用
sar 对有符号类型也有用,会设置符号位。


循环移位 pdf 257
对bcd的操作略

Logical Operations
and
not
or
xor

Working with strings

The MOVS instruction
movsb moves a single byte
movsw movsw a word
movsl moves a doubleword

movs 使用隐含的源操作数和目的操作数,源操作数是esi寄存器,指向源字符串的位置。目的操作数是edi寄存器,指向被拷贝位置。

movl $output,%edi
LEA指令:
leal output,%edi

每次执行movs指令,esi和edi内容会自动变化。DF指令被清除,esi和edi会自动增加,反之自动减少,可以使用cld清除df标志,std设置df标志。
注:如果用std让指针倒退,movsw和movsl依然向前获得内存位置。


REP prefix
REP指令让紧随其后的指令重复执行,执行次数是ecx寄存器中的值。


Storing and loading strings
lods 用esi寄存器存储要载入字符串的位置,lods 增加或减少取决于df是否被设置。lods将一个string值放入eax寄存器。

stos 用edi寄存器当做目的寄存器,将一个字符串放入指定内存位置。esi是隐含的源操作数。

Comparing String
cmps instruction 隐含的源操作数和目的操作数分别为esi和edi,每执行一次,esi和edi中的值会根据df标记增加或减少。

Using REP with CMPS
REPE,REPNE,REPZ,REPNZ,这些指令检查zero flag ,rep不会检查zero flag。

Scanning Strings
scas instruction 隐含的目的操作数是edi寄存器,其中存有字符串的内存地址。指令执行时,edi中的值会根据df中的值的设定相应变化。scas将
指针指向的字符和al寄存器中的字符进行比较。
repe 扫描整个字符串找到不匹配的字符;
repne 扫描整个字符喘串找到匹配的字符。
eg. repne scasb

Finding a string length
eg.pdf 326

 

Using Functions

Writing functions
1.定义输入值
2.定义操作
3.定义输出值。

Defining input values
Using registers
Using global variables
Using the stack

Defining function processes
.type func1,@function
func1:

Defining output values
Place the result in one or more registers
Place the result in a global variable memory location.

Accessing functions
call functionName

Function placement
the functions do not have to be defined before they are called in the main program

Using registers
If you are calling a function that modifies registers the main program uses,it is crucial that you save the current state of the registers before calling the
function ,and then restore them after the function returns.PUSH or PUSHA can be used.


Using global data
pdf 336

Function prologue and epilogue p(339)

function:
pushl %ebp
movl %esp,%ebp
.
.
.
movl %ebp,%esp
popl %ebp
ret

Using Separate Function Files
Creating a separate function file
.section .text
.type area,@function
.globl area
area:


Using Command-Line Parameters

Analyzing the stack
Linux places four types of information into the program stack when the program starts:
1.The number of command-line parameters
2.The name of the program as executed from the shell prompt
3.Any command-line prameters included on the command line
4.All the current Linux environment variables at the start of the program.

Viewing environment variables p356
When no command-line parameters are specified,the environment variable section starts at offset 12 of the ESP register.


Creating Static Libraries
In Linux ,static library files are created using the ar command.
ar r libchap14.a *.o
ar t libchap14.a

ranlib 程序可以为静态库创建索引,加快链接速度。
ranlib *.a

 

Creating a shared library
gcc -shared 可以生成动态链接库

etc/ld.so.conf 文件中包含动态库的文件夹位置
ldconfig,当像conf文件中添加新的目录之后,必须运行ldconfig才可以更新ld.so.cache文件,否则无法找到该库。