int $0x80

printf strlen 구현 본문

컴퓨터공부/어셈블리어

printf strlen 구현

cd80 cd80 2014.01.15 15:48

리눅스상에서 printf를 구현합니다

사실 구현하는 함수는 puts지만 그냥 문자열출력함수를 구현한다는 의미에서 제목을 printf 구현으로 지었습니다


write 시스템콜을 이용해 구현할거기 때문에 write 시스템콜의 콜넘버를 알아야합니다

root@ubuntu:/home/study/first/programming# grep "__NR_write" /usr/include/*/*/*

/usr/include/i386-linux-gnu/asm/unistd_32.h:#define __NR_write 4

/usr/include/i386-linux-gnu/asm/unistd_32.h:#define __NR_writev 146

/usr/include/i386-linux-gnu/asm/unistd_64.h:#define __NR_write 1

/usr/include/i386-linux-gnu/asm/unistd_64.h:#define __NR_writev 20

/usr/include/i386-linux-gnu/asm/unistd_x32.h:#define __NR_write (__X32_SYSCALL_BIT + 1)

/usr/include/i386-linux-gnu/asm/unistd_x32.h:#define __NR_writev (__X32_SYSCALL_BIT + 516)

/usr/include/i386-linux-gnu/bits/syscall.h:#define SYS_write __NR_write

/usr/include/i386-linux-gnu/bits/syscall.h:#define SYS_writev __NR_writev

/usr/include/i386-linux-gnu/bits/syscall.h:#define SYS_write __NR_write

/usr/include/i386-linux-gnu/bits/syscall.h:#define SYS_writev __NR_writev

/usr/include/i386-linux-gnu/bits/syscall.h:#define SYS_write __NR_write

/usr/include/i386-linux-gnu/bits/syscall.h:#define SYS_writev __NR_writev

grep: /usr/include/linux/netfilter/ipset: Is a directory

root@ubuntu:/home/study/first/programming#


32비트 운영체제이므로 맨 첫번째줄에있는 4번을 사용하면됩니다

앞으로 구현하는 함수들을 다른 함수 구현에도 사용할 것이고

이를 위해 처음엔 test.s 에 main함수와 구현하는 함수를 구현해 구현하는 함수를 테스트해보고

함수가 제대로 동작하는것을 확인하면 header.inc 에 넣고 사용합니다


write시스템콜은

write(int fd, char buf[], len(buf)); 의 형식을 갖습니다

리눅스에선 stdin, stdout, stderr의 fd가 이미 정해져있습니다

0 - stdin

1 - stdout

2 - stderr

따라서 fd엔 1을 넣으면 됩니다


시스템콜은

eax - syscall 넘버

ebx - 첫번째 인자

ecx - 두번째 인자

edx - 세번째 인자

이렇게 세팅해 인터럽트 넘버 0x80으로 인터럽트 하면 됩니다


이 함수는 제가 사용할거기때문에 편의를 위해 write의 세번째인자는 printf내에서 두번째 인자의 길이를 계산해 넣어주게 했습니다


아래는 header.inc의 내용이고

printString:

        push %ebp

        mov %esp, %ebp

        push %ebx

        push %ecx

        push %edx

        push %esi


        mov $0x1, %ebx

        mov 0x8(%ebp), %ecx

        push %ecx

        call strlen

        mov %eax, %edx

mov $0x4, %eax

        int $0x80


pop %esi

pop %edx

pop %ecx

pop %ebx

leave

ret


strlen:

push %ebp

mov %esp, %ebp

push %esi

push %ecx


mov 0x8(%ebp), %esi

mov $0x0, %ecx


.strlen_loop:

movb (%esi), %al

cmpb $0x0, %al

je .strlen_finished

inc %esi

inc %ecx

jmp .strlen_loop

.strlen_finished:

mov %ecx, %eax

pop %ecx

pop %esi

leave

ret 

아래는 print.s에서 인클루드해 테스트하는 코드입니다

root@ubuntu:/home/study/first/programming# cat print.s

.text

.include "header.inc"


.globl main


main:

push %ebp

mov %esp, %ebp

push $string

call printString

leave

ret

.section .rodata

string:

.string "Hello, World\n"

root@ubuntu:/home/study/first/programming# ./print

Hello, World

root@ubuntu:/home/study/first/programming#

신고

'컴퓨터공부 > 어셈블리어' 카테고리의 다른 글

무한루프 원인 확인 및 패치  (0) 2014.01.16
취약프로그램 작성&공격  (0) 2014.01.15
gets 구현  (0) 2014.01.15
strcpy 구현  (0) 2014.01.15
printf strlen 구현  (1) 2014.01.15
1 Comments
댓글쓰기 폼