Assembly Language
glibc를 사용하지 않는 Linux elf64 예제
수색…
사용자 인터페이스
현대 컴퓨팅 시스템에서 진행되는 프로세싱의 80 %는 Linux, OSX 및 Windows 용 커널 코드와 같은 사용자 상호 작용을 필요로하지 않는다고 말할 수 있습니다. 그렇다면 키보드 ( 포인팅 장치 )와 콘솔을 통한 상호 작용 성이라는 두 가지 기본 원칙이 있습니다. 이 시리즈 및 다른 시리즈는 텍스트 기반 콘솔 (VT100 에뮬레이션) 및 키보드를 중심으로합니다.
그 자체로는이 예제는 매우 간단하지만보다 복잡한 알고리즘에 대한 필수적인 기본 요소입니다.
Subrtx.asm
STDIN equ 0
STDOUT equ 1
SYS_READ equ 0
SYS_WRITE equ 1
global gets, strlen, print, atoq
section .text
이것은 키보드만을위한 것이기 때문에 오류가 발생할 확률은 없음입니다. 가장 자주 상상할 수있는 프로그램은 버퍼 오버런을 피하기 위해 버퍼 크기를 고려할 수 있지만 간접적 인 경우 보장되지는 않습니다.
; =============================================================================
; Accept canonical input from operator for a maximum of EDX bytes and replace
; terminating CR with NULL.
; ENTER: RSI = Pointer to input buffer
; EDX = Maximum number of characters
; LEAVE: EAX = Number of characters entered
; R11 = Modified by syscall, all others preserved.
; FLAGS: ZF = Null entry, NZ otherwise.
; _____________________________________________________________________________
gets: push rcx
push rdi
xor eax, eax ; RAX = SYS_READ
mov edi, eax ; RDI = STDIN
syscall
; TODO: Should probably do some error trapping here, especially for
; buffer overrun, but I'll see if it becomes an issue over time.
dec eax ; Bump back to CR
mov byte [rsi+rax], 0 ; Replace it with NULL
pop rdi
pop rcx
ret
우선, 이것은 write (2)의 문자열 길이를 코드화하거나 수동으로 계산할 필요성을 피하기위한 것입니다. 그런 다음 구분 기호를 통합하기로 결정 했으므로 이제는 모든 문자 (0 - FF)를 검색하는 데 사용할 수 있습니다. 예를 들어, 단어 줄 바꿈 텍스트에 대한 가능성이 열리므로 레이블 strlen 은 일반적으로 결과가 보이는 문자의 숫자가 될 것이라고 생각하므로 약간의 잘못된 이름입니다.
; =============================================================================
; Determine length, including terminating character EOS. Result may include
; VT100 escape sequences.
; ENTER: RDI = Pointer to ASCII string.
; RCX Bits 31 - 08 = Max chars to scan (1 - 1.67e7)
; 07 - 00 = Terminating character (0 - FF)
; LEAVE: RAX = Pointer to next string (optional).
; FLAGS: ZF = Terminating character found, NZ otherwise (overrun).
; _____________________________________________________________________________
strlen: push rcx ; Preserve registers used by proc so
push rdi ; it's non-destructive except for RAX.
mov al, cl ; Byte to scan for in AL.
shr ecx, 8 ; Shift max count into bits 23 - 00
; NOTE: Probably should check direction flag here, but I always set and
; reset DF in the process that is using it.
repnz scasb ; Scan for AL or until ECX = 0
mov rax, rdi ; Return pointer to EOS + 1
pop rdi ; Original pointer for proglogue
jz $ + 5 ; ZF indicates EOS was found
mov rax, rdi ; RAX = RDI, NULL string
pop rcx
ret
이 절차의 목적은 호출 프로 시저에서 루프 디자인을 단순화하는 것입니다.
; =============================================================================
; Display an ASCIIZ string on console that may have embedded VT100 sequences.
; ENTER: RDI = Points to string
; LEAVE: RAX = Number of characters displayed, including EOS
; = Error code if SF
; RDI = Points to byte after EOS.
; R11 = Modified by syscall all others preserved
; FLAGS: ZF = Terminating NULL was not found. NZ otherwise
; SF = RAX is negated syscall error code.
;______________________________________________________________________________
print: push rsi
push rdx
push rcx
mov ecx, -1 << 8 ; Scan for NULL
call strlen
push rax ; Preserve point to next string
sub rax, rdi ; EAX = End pntr - Start pntr
jz .done
; size_t = write (int STDOUT, char *, size_t length)
mov edx, eax ; RDX = length
mov rsi, rdi ; RSI = Pointer
mov eax, SYS_WRITE
mov edi, eax ; RDI = STDOUT
syscall
or rax, rax ; Sets SF if syscall error
; NOTE: This procedure is intended for console, but in the event STDOUT is
; redirected by some means, EAX may return error code from syscall.
.done: pop rdi ; Retrieve pointer to next string.
pop rcx
pop rdx
pop rsi
ret
마지막으로 이러한 기능을 사용하는 방법의 예입니다.
Generic.asm
global _start
extern print, gets, atoq
SYS_EXIT equ 60
ESC equ 27
BSize equ 96
section .rodata
Prompt: db ESC, '[2J' ; VT100 clear screen
db ESC, '[4;11H' ; " Position cursor to line 4 column 11
db 'ASCII -> INT64 (binary, octal, hexidecimal, decimal), '
db 'Packed & Unpacked BCD and floating point conversions'
db 10, 10, 0, 9, 9, 9, '=> ', 0
db 10, 9, 'Bye'
db ESC, '[0m' ; VT100 Reset console
db 10, 10, 0
section .text
_start: pop rdi
mov rsi, rsp
and rsp, byte 0xf0 ; Align stack on 16 byte boundary.
call main
mov rdi, rax ; Copy return code into ARG0
mov eax, SYS_EXIT
syscall
; int main ( int argc, char *args[] )
main: enter BSize, 0 ; Input buffer on stack
mov edi, Prompt
call print
lea rsi, [rbp-BSize] ; Establish pointer to input buffer
mov edx, BSize ; Max size for read(2)
.Next: push rdi ; Save pointer to "=> "
call print
call gets
jz .done
call atoq ; Convert string pointed to by RSI
pop rdi ; Restore pointer to prompt
jmp .Next
.done: call print ; RDI already points to "Bye"
xor eax, eax
leave
ret
Makefile
OBJECTS = Subrtx.o Generic.o
Generic : $(OBJECTS)
ld -oGeneric $(OBJECTS)
readelf -WS Generic
Generic.o : Generic.asm
nasm -g -felf64 Generic.asm
Subrtx.o : Subrtx.asm
nasm -g -felf64 Subrtx.asm
clean:
rm -f $(OBJECTS) Generic
Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow