Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #==========================================
- #------------------data--------------------
- #==========================================
- .section .data
- RTLWriteIntegerBuffer:
- .byte 0x3b,0x3d,0x3e,0x00 # <=>\0
- .byte 0x3b,0x3d,0x3e,0x00 # <=>\0
- .byte 0x3b,0x3d,0x3e,0x00 # <=>\0
- ReadCharInited:
- .byte 0
- IsEOF:
- .byte 0
- #==========================================
- #-------------------bss--------------------
- #==========================================
- .section .bss
- .lcomm ReadCharBuffer, 1
- .lcomm ReadCharBytesRead,4
- .macro pushall
- pushq %rax
- pushq %rbx
- pushq %rcx
- pushq %rdx
- pushq %rsp
- pushq %rbp
- pushq %rsi
- pushq %rdi
- .endm
- .macro popall
- popq %rdi
- popq %rsi
- popq %rbp
- popq %rsp
- popq %rdx
- popq %rcx
- popq %rbx
- popq %rax
- .endm
- #==========================================
- #------------------text--------------------
- #==========================================
- .section .text
- .globl _start
- _start:
- jmp StubEntryPoint
- /*
- 1. RTLHalt — остановка программы,
- 2. X RTLWriteChar — запись char’а на stdout,
- 3. X RTLWriteInteger — запись целого на stdout, принимает два параметра: число и ширину вывода,
- 4. X RTLWriteLn — выводит на stdout символ новой строки (13, 10),
- 5. X RTLReadChar — считывает символ из stdin, результат кладёт в EAX,
- 6. RTLReadInteger — считывает целое из stdin, результат кладёт в EAX,
- 7. RTLReadLn — пропускает стандартный ввод до конца файла или ближайшего перевода строки,
- 8. X RTLEOF — возвращает в EAX число 1, если достигнут конец файла (следующий символ прочитать невозможно) или 0 в противном случае,
- 9. RTLEOLN — возвращает в EAX число 1, если следующий символ \n, 0 — в противном случае.
- **/
- #------------------------------------------
- #----------------WriteChar-----------------
- #------------------------------------------
- RTLWriteChar:
- pushall
- movq %rsp, %rbp #better use base ptr to stack frame
- #instead of stack itself
- movq $1, %rax #syscall №
- movq $1, %rdi #param1, fd
- movq %rbp, %rsi #p2, buf
- addq $72, %rsi #stack:[0-ret,8-arg1,16-arg2]
- movq $1, %rdx #p3, count
- syscall
- popall
- ret
- #------------------------------------------
- #--------------WriteInteger----------------
- #------------------------------------------
- RTLWriteInteger:
- pushq %rbp
- movq %rsp, %rbp
- movq 16(%rbp), %rbx #arg: count (stdout width)
- movq 24(%rbp), %rax #arg: num
- cmpq $0, %rax
- jnl RTLWriteIntegerNotSigned
- negq %rax
- decq %rbx
- pushq $'-' #dont forget to pop
- call RTLWriteChar
- addq $8, %rsp #pop
- RTLWriteIntegerNotSigned:
- xorq %rcx, %rcx
- pushq %rax
- pushq %rbx
- RTLWriteIntegerPreCheckLoop:
- testq %rax, %rax
- jz RTLWriteIntegerPreCheckLoopDone
- incq %rcx
- movq $10, %rbx
- xorq %rdx, %rdx
- idiv %rbx
- jmp RTLWriteIntegerPreCheckLoop
- RTLWriteIntegerPreCheckLoopDone:
- testq %rcx, %rcx
- setz %dl
- orb %dl, %cl
- popq %rbx
- popq %rax
- subq %rcx, %rbx
- cmpq $0, %rbx
- jle RTLWriteIntegerNotPadding
- pushq %rcx
- RTLWriteIntegerPaddingLoop:
- pushq $' ' #pop!
- call RTLWriteChar
- addq $8, %rsp #pop
- decq %rbx
- jnz RTLWriteIntegerPaddingLoop
- popq %rcx
- RTLWriteIntegerNotPadding:
- #find last digit's address:
- #we write from right to left cuz each time we divide number by 10, we only know it's right-most digit
- #so we need to write right-most digit into right-most byte:
- #e.g: num=-123; count=4
- #init buffer: |0x3b|0x3d|0x3e|0x00|0x3b|...
- #1st iter: |0x3b|0x3d| 3d |0x00|0x3b|...
- #2st iter: |0x3b| 2d | 3d |0x00|0x3b|...
- #3st iter: | 1d | 2d | 3d |0x00|0x3b|...
- movq $RTLWriteIntegerBuffer, %rdi #leaq RTLWriteIntegerBuffer-1(%rcx), %rdi
- addq %rcx, %rdi #-||-
- decq %rdi #-||-
- #LEA EDI,[OFFSET RTLWriteIntegerBuffer+ECX-1]
- pushq %rcx #we dont care if (count < real_num_width)
- RTLWriteIntegerLoop:
- movq $10, %rsi
- xorq %rdx, %rdx
- idiv %rsi
- #convert to string
- movq %rdx, %rbx #leaq '0'(%rdx), %rbx equivalent
- addq $'0', %rbx #-||-
- movb %bl, (%rdi)
- decq %rdi
- loop RTLWriteIntegerLoop
- popq %rcx
- #invoke WriteFile
- movq $1, %rax #syscall
- movq $1, %rdi #param1, fd
- movq $RTLWriteIntegerBuffer, %rsi #p2, buf
- movq %rcx, %rdx #p3, count
- syscall
- popq %rbp
- ret
- #------------------------------------------
- #-----------------WriteLn------------------
- #------------------------------------------
- RTLWriteLn:
- pushq %rbp
- movq %rsp, %rbp
- pushq $13
- call RTLWriteChar
- addq $8, %rsp
- pushq $10
- call RTLWriteChar
- addq $8, %rsp
- popq %rbp
- ret
- ReadCharEx:
- pushall
- movq %rsp, %rbp
- movq $0, %rax
- movq $0, %rdi
- movq $ReadCharBuffer, %rsi
- movq $1, %rdx
- syscall
- testq %rax, %rax
- setz %al
- orb %al, IsEOF
- popall
- ret
- ReadCharInit:
- cmpb $0, ReadCharInited
- jnz ReadInitDone
- call ReadCharEx
- movb $1, ReadCharInited
- ReadInitDone:
- ret
- #------------------------------------------
- #----------------ReadChar------------------
- #------------------------------------------
- RTLReadChar:
- call ReadCharInit
- movzx ReadCharBuffer, %rax #movq (ReadCharBuffer), %rax
- call ReadCharEx
- ret
- #------------------------------------------
- #--------------ReadInteger-----------------
- #------------------------------------------
- RTLReadInteger:
- call ReadCharInit
- pushall
- movq %rsp, %rbp
- xorq %rax, %rax
- xorq %rbx, %rbx
- leaq 1(%rax,%rbx,1), %rcx
- ReadIntegerSkipWhiteSpace:
- cmpb $0, (IsEOF)
- jnz ReadIntegerDone
- cmpb $0, (ReadCharBuffer)
- je ReadIntegerSkipWhiteSpaceDone
- cmpb $32, (ReadCharBuffer)
- ja ReadIntegerSkipWhiteSpaceDone
- call ReadCharEx
- jmp ReadIntegerSkipWhiteSpace
- ReadIntegerSkipWhiteSpaceDone:
- cmpb $'-', (ReadCharBuffer)
- jne ReadIntegerNotSigned
- negq %rcx
- call ReadCharEx
- ReadIntegerNotSigned:
- ReadIntegerLoop:
- movzx ReadCharBuffer, %rbx
- cmpb $'0', %bl
- jb ReadIntegerDone
- cmpb $'9', %bl
- ja ReadIntegerDone
- imul $10, %rax
- lea -'0'(%rax,%rbx,1), %rax
- call ReadCharEx
- jmp ReadIntegerLoop
- ReadIntegerDone:
- imul %rcx
- popall
- ret
- #------------------------------------------
- #------------------ReadLn------------------
- #------------------------------------------
- RTLReadLn:
- call ReadCharInit
- cmpb $0, IsEOF
- jne ReadLnDone
- movb ReadCharBuffer, %bl
- cmpb $10, %bl
- je ReadLnDone
- call ReadCharEx
- jmp RTLReadLn
- ReadLnDone:
- ret
- #------------------------------------------
- #-------------------EOF--------------------
- #------------------------------------------
- RTLEOF:
- movq (IsEOF), %rax
- ret
- #------------------------------------------
- #------------------EOLN--------------------
- #------------------------------------------
- RTLEOLN:
- cmpb $10, (ReadCharBuffer)
- seteb %bl
- ret
- #------------------------------------------
- #------------------Halt--------------------
- #------------------------------------------
- RTLHalt:
- movq $60, %rax
- movq $0, %rdi
- syscall
- StubEntryPoint:
- #syscall mmap here
- /*call RTLWriteLn
- call RTLReadChar #read from stdin to rax
- pushq %rax
- call RTLWriteChar #write from rax to stdout
- addq $8, %rsp
- pushq $'A'
- call RTLWriteChar #write 'A'
- addq $8, %rsp
- */
- pushq $-123
- pushq $5
- call RTLWriteInteger
- call RTLWriteLn
- pushq $'A'
- call RTLWriteChar #write 'A'
- addq $8, %rsp
- #syscall munmap here
- call RTLHalt
- /*
- gdb:
- info files
- b *0x4000xx
- run
- si 1
- ni 1
- x/5i $pc
- x/8g $sp
- info registers (i r)
- p $rax
- set $rax = 0x123
- */
Advertisement
Add Comment
Please, Sign In to add comment