Estoy creando una aplicación simple sin glibc en Linux de 64 bits. Pero no sé cómo conseguir argumentos.
Busqué en Google y descubrí que RDI es argc, RSI es argv. Pero no funcionó.
Vi registros cuando la función _start comienza a usar gdb, pero tanto RDI como RSI eran 0x0. También probé con la aplicación de ensamblaje más simple, pero el resultado fue el mismo. RDI y RSI fue 0x0. Creo que argc no debería ser 0x0 incluso si no pasé argumentos al programa.
_start: jmp $Aquí está el código C que probé:
//Print Hello world WITHOUT standard library //ONLY WITH SYSTEM CALL #define ReadRdi(To) asm("movq %%rdi,%0" : "=r"(To)); #define ReadRsi(To) asm("movq %%rsi,%0" : "=r"(To)); void __Print(const char *str); void __Exit(); void Test(const char *a){ long aL; ReadRdi(aL); char *aC = (int) aL; __Print("Test argument: "); __Print(aC); __Print("\n"); } void _start() { long argcL; long argvL; ReadRdi(argcL); ReadRsi(argvL); int argc = (int) argcL; char **argv = (char **) argvL; __Print("Arguments: "); for(int i = 0; i < argc; i ++) { __Print(argv[i]); __Print(", "); } __Print("\n"); Test("Hello, world!"); __Exit(); }El resultado es:
Arguments: Test argument: Hello, world!Revisé la pila (valor de memoria en RBP ~ RSP) usando gdb, pero parecía que no había nada.
Traté de cambiar
void _start() { long argcL; long argvL; ReadRdi(argcL); ReadRsi(argvL); int argc = (int) argcL; char **argv = (char **) argvL; __Print("Arguments: ");para
void _start(int argc, char **argv) { __Print("Arguments: ");pero aún no puedo ver ningún resultado de argumentos.
__Imprimir imprime el mensaje (usando la llamada al sistema sys_write), __Exit sale del programa (usando la llamada al sistema sys_exit).
Imprimir.asm:
section .text global __Print __Print: mov rdx, 0 push rdi jmp .count .count: add rdx, 1 add rdi, 1 cmp byte[rdi], 0 jne .count .print: pop rdi mov rcx, rdi ;message to write mov rbx, 1 ;file descriptor (stdout) mov rax, 4 ;system call number (sys_write) int 0x80 ;call kernel retSalir.asm:
section .text global __Exit __Exit: mov rax,1 ;system call number (sys_exit) int 0x80AGREGAR: me vinculé con este comando:
gcc -o sysHello Exit.o Print.o sysHello.o -nostdlib -nodefaultlibs -gLo más fácil será escribir _start en asm y hacer que llame a sus funciones C usando la convención de llamada estándar.
Consulte la wiki de x86 para obtener enlaces al documento ABI que describe dónde encontrar todo al iniciar el proceso. (O use el enlace en el comentario de Ian).
Escribir _start como una función C requeriría asm en línea, porque no hay una forma estándar de decirle al compilador que argc es donde normalmente va la dirección de retorno. Por lo tanto, es más fácil escribirlo directamente en asm y hacer que call main después de colocar argumentos en los registros para la convención de llamada normal.
Un fragmento de un programa asm que uso para probar cosas con contadores de rendimiento:
cmp dword [rsp], 2 jg addrmode_lat_3comp ; argc > 2 ; $(seq 2) jge addrmode_lat_1comp ; argc >= 2 ; $(seq 1) jmp loadlat_1comp ; argc < 2 ; $(seq 0) Salta a uno de los tres bucles, dependiendo de si lo ejecuto con 2, 1 o sin argumentos, probando argc . Utiliza la sintaxis NASM.