C Función de lenguaje Llamada de llamadas Análisis de ensamblaje

您所在的位置:网站首页 xmi0 C Función de lenguaje Llamada de llamadas Análisis de ensamblaje

C Función de lenguaje Llamada de llamadas Análisis de ensamblaje

2023-03-10 20:52| 来源: 网络整理| 查看: 265

La cara de una persona está llena de la imagen. En la luz débil, los detalles de la cara no se pueden ver. Solo se puede ver que sus huesos de cejas y pómulos son muy altos, y sus labios son largos y delgados. La lente continúa cerrando esto. Esto parece ser poco probable que esté cerca. Un par de ojos profundos están llenos de imágenes. Hay algunas manchas de luz plateadas en las pupilas oscuras, que son el cielo estrellado deformado reflejado en él. La imagen se fijó y sonó un tweet afilado, y el riesgo le dijo a la gente que el sistema de alerta temprana había llamado a la policía. "¿Por qué?", ​​Preguntó el ingeniero jefe perplejo. "El tiempo de esta persona primitiva que mira el cielo estrellado excedió el umbral de advertencia, y ha sido completamente curioso sobre el universo. Hasta ahora, se han observado diez incidentes de exceso de iluminación en diferentes lugares, que cumplen con las condiciones de alarma. " "Si no recuerdo mal, usted dijo anteriormente que solo cuando aparece la civilización de una civilización de un proceso de energía creativa, el sistema de alerta temprana llamará a la policía". "¿No ves tal civilización?" El texto se selecciona de "Chaowen Tao" de Liu Cixin

Conocimiento básico

1 Instrucciones de llamadas Cambiar la dirección del programa y necesita guardar la pila de valor de la IP original [5]. 2 Pushq s presionando equivalencia de comando:

%rsp ← %rsp - 8 (%rsp) ← S

PushQ Presione un valor de un ocho byte. La imagen en la cita [3] se copia aquí, tomando un impulso como ejemplo, este comando presiona el valor de un cuatro byte.

El 3 %de RSP apunta a la parte superior (dirección baja), %de RBP a la parte superior de la pila (dirección alta)

Código del programa C

number.h

#pragma once typedef struct __attribute__((packed, aligned(4))){ int a; int b; double c; double d; }Number; Number number_add_v1(Number a,Number b); Number* number_add_v2(Number *a,Number *b);

number.c

#include #include #include #include "number.h" Number number_add_v1(Number a,Number b){ Number c; c.a=a.a+b.a; c.b=a.b+b.b; c.c=a.c+b.c; c.d=a.d+b.d; return c; } Number* number_add_v2(Number *a,Number *b){ Number *c; c=(Number*)malloc(sizeof(Number)); c->a=a->a+b->a; c->b=a->b+b->b; c->c=a->c+b->c; c->d=a->d+b->d; return c; }

main.c

#include #include #include "number.h" void debug_value(int c){ } int main(){ Number a; Number b; a.a=1; a.b=2; a.c=3.2; a.d=4.3; b.a=5; b.b=6; b.c=7.5; b.d=8.6; Number c=number_add_v1(a,b); debug_value(c.b); Number *e=number_add_v2(&a,&b); debug_value(e->a); free(e); return 0; }

CMakeLists.txt

PROJECT(project) cmake_minimum_required(VERSION 2.6) SET(CMAKE_BUILD_TYPE "Debug") include_directories(${CMAKE_SOURCE_DIR}/) set(num_LIB ${CMAKE_SOURCE_DIR}/number.c ) add_library(num STATIC ${num_LIB}) set(EXECUTABLE_NAME "t_test") add_executable(${EXECUTABLE_NAME} ${CMAKE_SOURCE_DIR}/main.c) target_link_libraries(${EXECUTABLE_NAME} num) Análisis del código de ensamblaje Generar ensamblaje: gcc -S -o main.s main.c gcc -S -o number.s number.c main.s .file "main.c" .text .globl debug_value .type debug_value, @function debug_value: .LFB5: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl %edi, -4(%rbp) nop popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE5: .size debug_value, .-debug_value .globl main .type main, @function main: .LFB6: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $112, %rsp movq %fs:40, %rax movq %rax, -8(%rbp) xorl %eax, %eax movl $1, -96(%rbp) movl $2, -92(%rbp) movsd .LC0(%rip), %xmm0 movsd %xmm0, -88(%rbp) movsd .LC1(%rip), %xmm0 movsd %xmm0, -80(%rbp) movl $5, -64(%rbp) movl $6, -60(%rbp) movsd .LC2(%rip), %xmm0 movsd %xmm0, -56(%rbp) movsd .LC3(%rip), %xmm0 movsd %xmm0, -48(%rbp) leaq -32(%rbp), %rax pushq -48(%rbp) pushq -56(%rbp) pushq -64(%rbp) pushq -80(%rbp) pushq -88(%rbp) pushq -96(%rbp) movq %rax, %rdi call [email protected] addq $48, %rsp movl -28(%rbp), %eax movl %eax, %edi call debug_value leaq -64(%rbp), %rdx leaq -96(%rbp), %rax movq %rdx, %rsi movq %rax, %rdi call [email protected] movq %rax, -104(%rbp) movq -104(%rbp), %rax movl (%rax), %eax movl %eax, %edi call debug_value movq -104(%rbp), %rax movq %rax, %rdi call [email protected] movl $0, %eax movq -8(%rbp), %rcx xorq %fs:40, %rcx je .L4 call [email protected] .L4: leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE6: .size main, .-main .section .rodata .align 8 .LC0: .long 2576980378 .long 1074370969 .align 8 .LC1: .long 858993459 .long 1074869043 .align 8 .LC2: .long 0 .long 1075707904 .align 8 .LC3: .long 858993459 .long 1075917619 .ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits Análisis de fragmentos de código principal.

Valor de la variable a:

movl $1, -96(%rbp) movl $2, -92(%rbp) movsd .LC0(%rip), %xmm0 movsd %xmm0, -88(%rbp) movsd .LC1(%rip), %xmm0 movsd %xmm0, -80(%rbp)

Valor de la variable b:

movl $5, -64(%rbp) movl $6, -60(%rbp) movsd .LC2(%rip), %xmm0 movsd %xmm0, -56(%rbp) movsd .LC3(%rip), %xmm0 movsd %xmm0, -48(%rbp)

Variable C Space de almacenamiento -32 (%RBP). Mantenga la dirección de la variable C en%RAX

leaq -32(%rbp), %rax

Pila de presión variable

PushQ -48 (%RBP) // Copiar B.D PushQ -56 (%RBP) // Copiar B.C Pushq -64 (%RBP) // Copiar B.A B.B Pushq -80 (%RBP) // Copiar A.D Pushq -88 (%RBP) // Copiar A.C Pushq -96 (%RBP) // Copia A.A A.B

Mantenga la dirección de la variable C en%RDI, llame a la función Number_add_V1 para realizar la adición del método.

movq %rax, %rdi call [email protected] number.s .file "number.c" .text .globl number_add_v1 .type number_add_v1, @function number_add_v1: .LFB5: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movq %rdi, -40(%rbp) movl 16(%rbp), %edx movl 40(%rbp), %eax addl %edx, %eax movl %eax, -32(%rbp) movl 20(%rbp), %edx movl 44(%rbp), %eax addl %edx, %eax movl %eax, -28(%rbp) movsd 24(%rbp), %xmm1 movsd 48(%rbp), %xmm0 addsd %xmm1, %xmm0 movsd %xmm0, -24(%rbp) movsd 32(%rbp), %xmm1 movsd 56(%rbp), %xmm0 addsd %xmm1, %xmm0 movsd %xmm0, -16(%rbp) movq -40(%rbp), %rcx movq -32(%rbp), %rax movq -24(%rbp), %rdx movq %rax, (%rcx) movq %rdx, 8(%rcx) movq -16(%rbp), %rax movq %rax, 16(%rcx) movq -40(%rbp), %rax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE5: .size number_add_v1, .-number_add_v1 .globl number_add_v2 .type number_add_v2, @function number_add_v2: .LFB6: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $32, %rsp movq %rdi, -24(%rbp) movq %rsi, -32(%rbp) movl $24, %edi call [email protected] movq %rax, -8(%rbp) movq -24(%rbp), %rax movl (%rax), %edx movq -32(%rbp), %rax movl (%rax), %eax addl %eax, %edx movq -8(%rbp), %rax movl %edx, (%rax) movq -24(%rbp), %rax movl 4(%rax), %edx movq -32(%rbp), %rax movl 4(%rax), %eax addl %eax, %edx movq -8(%rbp), %rax movl %edx, 4(%rax) movq -24(%rbp), %rax movsd 8(%rax), %xmm1 movq -32(%rbp), %rax movsd 8(%rax), %xmm0 addsd %xmm1, %xmm0 movq -8(%rbp), %rax movsd %xmm0, 8(%rax) movq -24(%rbp), %rax movsd 16(%rax), %xmm1 movq -32(%rbp), %rax movsd 16(%rax), %xmm0 addsd %xmm1, %xmm0 movq -8(%rbp), %rax movsd %xmm0, 16(%rax) movq -8(%rbp), %rax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE6: .size number_add_v2, .-number_add_v2 .ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits Número_add_v1 Análisis de fragmento de código

Ingrese la función número_add_v1, primero presione la pila, guarde RBP y asigne RSP a RBP. El RBP puede asignar el espacio de dirección de las variables locales en el espacio bajo desde el suelo.

pushq %rbp movq %rsp, %rbp

%RDI transmitió la dirección de la variable C en la función principal.

movq %rdi, -40(%rbp)

Análisis de análisis y operación en la función:

// Por primera vez, la operación de armonía C.A = A.A+B.A; Movl 16 (%RBP),%EDX // Obtener la copia de A.A, Contenido en la pila, correspondiente a PushQ -96 (%RBP) en Main Movl 40 (%RBP),%EAX // Obtener la copia de B.A, Contenido en la pila, correspondiente a PushQ -64 (%RBP) en Main addl %edx, %eax // El resultado se almacena en -32 (%RBP) y el espacio en la función movl %eax, -32(%rbp) // la segunda vez para resumir las operaciones c.b = a.b+b.b; movl 20(%rbp), %edx movl 44(%rbp), %eax addl %edx, %eax // El resultado se almacena en -28 (%RBP) y el espacio en la función movl %eax, -28(%rbp) // La tercera vez para la operación de paz C.C = A.C+B.C; movsd 24(%rbp), %xmm1 movsd 48(%rbp), %xmm0 addsd %xmm1, %xmm0 // El resultado se almacena en -24 (%RBP) y el espacio en la función movsd %xmm0, -24(%rbp) // La cuarta vez para la operación pacífica C.D = A.D+B.D; movsd 32(%rbp), %xmm1 movsd 56(%rbp), %xmm0 addsd %xmm1, %xmm0 // El resultado se almacena en -16 (%RBP) y el espacio en la función movsd %xmm0, -16(%rbp)

La dirección del 1 %de RBP compensó 16 bytes almacena el valor de A. A presionando la pila. El comando de llamada se presiona una vez, Pushq %RBP Press una vez, por lo que debe cambiar por 16 bytes. La diferencia entre 2 16 (%RBP) y 40 (%RBP) es de 24 bytes. Estos dos valores tienen tres veces la operación de pila en la función principal, y la diferencia de dirección es solo 24 bytes.

pushq -64(%rbp) pushq -80(%rbp) pushq -88(%rbp) pushq -96(%rbp)

Después de que se complete la operación de la adición, los datos de datos deben almacenarse en la variable C en la función principal. Los soportes de registro más indican la operación de direccionamiento.

MOVQ -40 (%RBP),%RCX // Actación La dirección de la variable C en%RCX Registro movq -32(%rbp), %rax movq -24(%rbp), %rdx Movq %RAX, ( %RCX) // La primera dirección, Store C.A y C.B Movq %RDX, 8 ( %RCX) // La segunda dirección, almacena C.C movq -16(%rbp), %rax Movq %RAX, 16 ( %RCX) // La tercera dirección, almacena C.D

Después de que la función regresa, el -32 (%RBP) en la función principal, la dirección correspondiente es el resultado de la ejecución number_add_v1.

Número_add_v2 Análisis de fragmento de código

La operación del puntero se realiza en número_add_v2. La función principal es llamar a número_add_v2, y los parámetros deben estar preparados. La dirección del primer parámetro se almacena en%RDI, y el segundo parámetro se almacena en%RSI.

Leaq -64 ( %RBP), %rdx // La dirección de la variable B Leaq -96 ( %RBP), %RAX // Variable A Dirección movq %rdx, %rsi movq %rax, %rdi call [email protected] // %Número de almacenamiento RAX_Add_V2 Valor de retorno movq %rax, -104(%rbp)

Después de ingresar a la función, la dirección del parámetro se coloca en el espacio de la pila. Llame al espacio de dirección de la dirección espacial asignada por MALLOC en -8 (%RBP).

MovQ%RDI, -24 (%RBP) // La primera dirección de parámetro se almacena en -24 (%RBP). MovQ%RSI, -32 (%RBP) // La segunda dirección de parámetro se almacena en -32 (%RBP). movl $24, %edi call [email protected] movq %rax, -8(%rbp)

Análisis de análisis y operación en la función:

// Por primera vez, armonía c-> a = a-> a+b-> a; MoVQ -24 ( %RBP), %RAX // A-> A DIRECCIÓN Movl ( %RAX), %EDX // A-> Un valor almacenado %EDX MOVQ -32 ( %RBP), %RAX // B-> A DIRECCIÓN Movl ( %RAX), %EAX // B-> Un valor almacenado en la entrada de valor %EDX ADDL %EAX, %EDX // Buscando paz MOVQ -8 ( %RBP), %RAX // Obtenga la dirección Movl %EDX, ( %RAX) // Los resultados almacenan en el espacio de direcciones de distribución // busca la segunda vez para encontrar c-> b = a-> b+b-> b; MoVQ -24 ( %RBP), %RAX // A-> A DIRECCIÓN // Ponga la dirección de A-> A 4 bytes, es decir, la dirección de A-> B, dirección y mueva el valor a%EDX movl 4(%rax), %edx MOVQ -32 ( %RBP), %RAX // B-> A DIRECCIÓN // Ponga la dirección de b-> a 4 bytes, es decir, la dirección de b-> b, dirección y mueva el valor a%eax movl 4(%rax), %eax ADDL %EAX, %EDX // Buscando paz movq -8(%rbp), %rax movl %edx, 4(%rax) // por tercera vez, c-> c = a-> c+b-> c; movq -24(%rbp), %rax movsd 8(%rax), %xmm1 movq -32(%rbp), %rax movsd 8(%rax), %xmm0 addsd %xmm1, %xmm0 movq -8(%rbp), %rax movsd %xmm0, 8(%rax) // El cuarto secuencial y c-> d = a-> d+b-> d; movq -24(%rbp), %rax movsd 16(%rax), %xmm1 movq -32(%rbp), %rax movsd 16(%rax), %xmm0 addsd %xmm1, %xmm0 movq -8(%rbp), %rax movsd %xmm0, 16(%rax) // Malloc asignó la dirección de la distribución de%RAX como valor de retorno movq -8(%rbp), %rax otro

En la parte inferior de Main.s, hay algunos datos constantes. Esto está representado por dos datos de cuatro bytes de datos de doble tipo.

.LC0: .long 2576980378 .long 1074370969 .align 8

Escriba un programa, resultados de entrada: 2576980378 1074370969

#include typedef struct{ union{ double decimal; struct{ int a; int b; }v; }; }Double2Int_t; int main(){ double value=3.2; Double2Int_t decimal; decimal.decimal=value; std::cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3