Автор Тема: Обращение к ядру на ассемблере  (Прочитано 8969 раз)

Оффлайн keremet

  • Global Moderator
  • ROOT
  • *****
  • Сообщений: 463
  • Репутация: +237/-0
    • Просмотр профиля
    • OpenSolaris
Обращение к ядру на ассемблере
« : Март 29, 2014, 11:38:51 pm »
.text
.globl _start

_start:
   pushl   $message_l
   pushl   $message
   pushl   $1
   movl   $4,%eax
   pushl   %eax
   syscall
   addl   $16,%esp
   
   xorl   %eax,%eax
   pushl   %eax
   incl   %eax
   pushl   %eax
   syscall
   hlt
.data
message:
   .string "HW!\n"
message_l = .-message-1

Компиляция:
 as -o test.o test.s && ld -s test.o && ./a.out

Размер: 384 байта

Трассировка:
$ truss ./a.out
execve("./a.out", 0x08047AE4, 0x08047AEC)  argc = 1
HW!
write(1, " H W !\n", 4)            = 4
_exit(0)
$

Для сравнения программа на С:
#include <unistd.h>
int main(int agrc, char** agrv){
   write(1,"HW!\n",4);
   return 0;
}

gcc -O3 ggg.c

Размер 8128 байт
Формируемый ассемблерный код (gcc -S -O3 ggg.c )
   .file   "ggg.c"
   .section   .rodata.str1.1,"aMS",@progbits,1
.LC0:
   .string   "HW!\n"
   .text
   .p2align 2,,3
.globl main
   .type   main, @function
main:
   pushl   %ebp
   movl   %esp, %ebp
   subl   $8, %esp
   andl   $-16, %esp
   subl   $20, %esp
   pushl   $4
   pushl   $.LC0
   pushl   $1
   call   write
   xorl   %eax, %eax
   leave
   ret
   .size   main, .-main

Трассировка:
$ truss ./a.out
execve("a.out", 0x08047A7C, 0x08047A84)  argc = 1
sysconfig(_CONFIG_PAGESIZE)         = 4096
mmap(0x00000000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0) = 0xFEFB0000
mmap(0x00000000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0) = 0xFEFA0000
memcntl(0xFEFBE000, 27724, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
mmap(0x00000000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0) = 0xFEF90000
memcntl(0x08050000, 2580, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
resolvepath("/usr/lib/ld.so.1", "/lib/ld.so.1", 1023) = 12
getcwd("/data/compilation/asm", 1017)      = 0
resolvepath("/data/compilation/asm/a.out", "/data/compilation/asm/a.out", 1023) = 27
stat64("/data/compilation/asm/a.out", 0x08047720) = 0
open("/var/ld/ld.config", O_RDONLY)      Err#2 ENOENT
stat64("/usr/ccs/lib/libc.so.1", 0x08046F20)   Err#2 ENOENT
stat64("/lib/libc.so.1", 0x08046F20)      = 0
resolvepath("/lib/libc.so.1", "/lib/libc.so.1", 1023) = 14
open("/lib/libc.so.1", O_RDONLY)      = 3
mmapobj(3, 0x00020000, 0xFEF904D0, 0x08046F8C, 0x00000000) = 0
close(3)               = 0
memcntl(0xFEE30000, 188400, MC_ADVISE, MADV_WILLNEED, 0, 0) = 0
mmap(0x00010000, 24576, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON|MAP_ALIGN, -1, 0) = 0xFEE20000
getcontext(0x08047580)
getrlimit(RLIMIT_STACK, 0x08047578)      = 0
getpid()               = 1061 [1060]
lwp_private(0, 1, 0xFEE22A00)         = 0x000001C3
setustack(0xFEE22A60)
sysi86(SI86FPSTART, 0xFEF8700C, 0x0000133F, 0x00001F80) = 0x00000001
HW!
write(1, " H W !\n", 4)            = 4
_exit(0)


Улучшенная программа на С:
$ cat ggg_asm.h
static int inline write_asm(int fildes, const void *buf, int nbyte){
   asm("pushl %0"::"r"(nbyte));
   asm("pushl %0"::"r"(buf));
   asm("pushl %0"::"r"(fildes));
   asm("movl $4,%eax\n\t"
   "pushl   %eax\n\t"
   "syscall\n\t"
   "addl   $16,%esp");
   return 0;
}

static void inline exit_asm(int rel_value){
   asm("pushl %0"::"r"(rel_value));
   asm("movl $1,%eax\n\t"
   "pushl   %eax\n\t"
   "syscall\n\t"
   "addl   $8,%esp");   
}

$ cat ggg_asm.c
#include <ggg_asm.h>
void _start(){
   write_asm(1,"HW!\n",4);
   exit_asm(0);
}

Компиляция: gcc -fno-ident -I. -O3 -c -o ggg_asm.o ggg_asm.c && ld -s ggg_asm.o
Размер 444 байт
Формируемый ассемблерный код
   .file   "ggg_asm.c"
   .section   .rodata.str1.1,"aMS",@progbits,1
.LC0:
   .string   "HW!\n"
   .text
   .p2align 2,,3
.globl _start
   .type   _start, @function
_start:
   movl   $1, %ecx
   movl   $.LC0, %edx
   movl   $4, %eax
/APP
   pushl %eax
   pushl %edx
   pushl %ecx
   movl $4,%eax
   pushl   %eax
   syscall
   addl   $16,%esp
/NO_APP
   xorb   %al, %al
/APP
   pushl %eax
   movl $1,%eax
   pushl   %eax
   syscall
   addl   $8,%esp
/NO_APP
   ret
   .size   _start, .-_start

Трассировка:
$ truss ./a.out
execve("./a.out", 0x08047ABC, 0x08047AC4)  argc = 1
HW!
write(1, " H W !\n", 4)            = 4
_exit(0)

Оффлайн keremet

  • Global Moderator
  • ROOT
  • *****
  • Сообщений: 463
  • Репутация: +237/-0
    • Просмотр профиля
    • OpenSolaris
Re: Обращение к ядру на ассемблере
« Ответ #1 : Июнь 30, 2017, 08:09:57 pm »
gcc -O3 -fno-ident -I. -DLOCALE=\"ru_RU.UTF-8\" -c  set_lng.c
ld -s set_lng.o

Размер исполняемого файла около 500байт, но программа работает не на всех машинах. Может выдать ошибку Illegal Instruction (core dumped)

Оффлайн keremet

  • Global Moderator
  • ROOT
  • *****
  • Сообщений: 463
  • Репутация: +237/-0
    • Просмотр профиля
    • OpenSolaris
Re: Обращение к ядру на ассемблере
« Ответ #2 : Январь 11, 2018, 07:10:10 pm »
//gcc write2.c -nostdlib -lc
Значение переменных окружения
$ LD_LIBRARY_PATH=/lib time ./a.out
qwe

real        0.0
user        0.0
sys         0.0

sundev@sunhost:~/dwm$ time ./a.out
qwe

real   0m0.002s
user   0m0.000s
sys   0m0.002s


#define ECHO(S) write(1, S"\n", sizeof(S))

void _start(){
   ECHO("qwe");
   exit(0);
}