How to read input from STDIN in x86_64 assembly? -


i trying learn x86_64 assembly , trying standard input output today , stumbled upon post learning assembly - echo program name how same reading input stdin (using syscall instruction)? if know input integer , want read register?

edit: @daniel kozar's answer below helped me understand how stdin , stdout stuff work syscall instruction on linux. attempted write small program, reads number console input , prints ascii character corresponding number. if type 65 input, should output. , new line character. if @ all, helps 1 else :-)

section .text     global _start  _start:     mov rdi, 0x0      ; file descriptor = stdin = 0     lea rsi, [rsp+8]  ; buffer = address store bytes read     mov rdx, 0x2      ; number of bytes read     mov rax, 0x0      ; syscall number reading stdin     syscall           ; make syscall      xor rax, rax      ; clear off rax     mov rbx, [rsp+8]  ; read first byte read rsp+8 stdin call rbp     sub rbx, 0x30     ; since read character, obtained ascii value, subtract 0x30 number     , rbx, 0xff     ; ensures other last byte set 0 while last byte     mov rax, rbx      ; move value rax since want store final result in rax     shl rbx, 0x1      ; need multiply 10 can add digits read multiplying number 2 , 8 , adding them up, multiply 2 here     shl rax, 0x3      ; multiply 8 here     add rax, rbx      ; add 8 times multiplied value 2 times multiplied value 10 times multiplied value     mov rbx, [rsp+9]  ; read next byte (or digit)     sub rbx, 0x30     ; again digit value ascii value of digit's character     , rbx, 0xff     ; clear higher bytes     add rax, rbx      ; add rax unit's place value     mov [rsp+8], rax  ; move entire byte rax     mov rdi, 0x1      ; file descriptor = stdout     lea rsi, [rsp+8]  ; buffer = address write console     mov rdx, 0x1      ; number of bytes write     mov rax, 0x1      ; syscall number writing stdout     syscall           ; make syscall      xor rax, rax      ; clear off rax     mov rax, 0xa      ; move new line character rax     mov [rsp+8], rax  ; put on stack     mov rdi, 0x1      ; file descriptor = stdout     lea rsi, [rsp+8]  ; buffer = address write console     mov rdx, 0x1      ; number of bytes write     mov rax, 0x1      ; syscall number writing stdout     syscall           ; make syscall      mov rdi, 0        ; set exit status = 0     mov rax, 60       ; syscall number exit     syscall           ; make syscall 

edit 2: here attempt read unsigned 32-bit decimal integer standard input, store integer computations , write std out.

section .text         global _start  _start: ;read stdin         mov rdi, 0x0      ; file descriptor = stdin = 0         lea rsi, [rsp+8]  ; buffer = address store bytes read         mov rdx, 0xa      ; number of bytes read         mov rax, 0x0      ; syscall number reading stdin         syscall           ; make syscall   ; ascii decimal conversion         xor rax, rax      ; clear off rax         mov rbx, 0x0      ; initialize counter stores number of bytes in string representation of integer         lea rsi, [rsp+8]  ; address on stack first ascii byte of integer stored.  rnext:         mov rcx, [rsi]    ; read byte on stack @ address represented rsi         cmp rcx, 0xa      ; check if newline character         je  return        ; if done         cmp rbx, 0xa      ; or check if have read 10 bytes (the largest 32 bit number contains 10 digits, have process @ 10 bytes         jg  return        ; if done         sub rcx, 0x30     ; byte read, subtract 0x30/48 value ascii code. 0 == 0x30 in ascii, 1 == 0x31 in ascii , on.         , rcx, 0xff     ; clear off higher order bytes ensure there no interference         mov rdx, rax      ; need multiple 10 next byte goes unit's place , byte becomes ten's value. make copy         shl rax, 0x3      ; multiply original 8 (shift left 3 multiply 8)         shl rdx, 0x1      ; multiply copy 2 (shift left 1 multiply 2)         add rax, rdx      ; add these * 8 + * 2 * 10.         add rax, rcx      ; add digit @ units place original number         add rsi, 1        ; advance memory address 1 read next byte         inc rbx           ; increment digit counter         jmp rnext         ; loop until have read digits or max reached.  return:         push rax          ; push read number on stack  ; write new line         mov rax, 0xa      ; move new line character rax         mov [rsp+8], rax  ; put on stack         mov rdi, 0x1      ; file descriptor = stdout         lea rsi, [rsp+8]  ; buffer = address write console         mov rdx, 0x1      ; number of bytes write         mov rax, 0x1      ; syscall number writing stdout         syscall           ; make syscall   ; convert decimal bytes         xor  rdx, rdx     ; clear rdx stores obtains single digit of number convert ascii bytes         mov  r8, 0x0      ; initialize counter containing number of digits          pop  rax          ; pop read number stack         mov  rbx, 0xa     ; store divisor 10 decimals (base-10) in rbx. rbx divisor.  wnext:          div  rbx          ; divide number in rdx:rax rbx remainder in rdx         add  rdx, 0x30    ; add 0x30 ascii byte equivalent of remainder digit in number written display.         push rdx          ; push byte stack. because, individial digit bytes in reverse order. reverse order use stack         xor  rdx, rdx     ; clear rdx preparing next division         inc  r8           ; increment digits counter         cmp  rax, 0x0     ; continue until number becomes 0 when there no more digits write console.         jne  wnext        ; loop until there aren't more digits.  popnext:         cmp  r8, 0x0      ; check if counter contains number of digits write 0         jle  endw         ; if there no more digits write         mov  rdx, 0x1     ; number of bytes write         mov  rsi, rsp     ; buffer = address write console         mov  rdi, 0x1     ; file descriptor = stdout         mov  rax, 0x1     ; syscall number writing stdout         syscall           ; make syscall         dec  r8           ; decrement counter         pop  rbx          ; pop current digit written display preparing stack pointer next digit.         jmp  popnext      ; loop until counter contains number of digits goes down 0.  endw: ; write new line         xor rax, rax      ; clear off rax         mov rax, 0xa      ; move new line character rax         mov [rsp+9], rax  ; put on stack         mov rdi, 0x1      ; file descriptor = stdout         lea rsi, [rsp+9]  ; buffer = address write console         mov rdx, 0x1      ; number of bytes write         mov rax, 0x1      ; syscall number writing stdout         syscall           ; make syscall  ; exit         mov rdi, 0        ; set exit status = 0         mov rax, 60       ; syscall number exit         syscall           ; make syscall 

first of : there no variables in assembly. there labels kind of data. data is, design, untyped - @ least in real assemblers, not hla (e.g. masm).

reading standard input achieved using system call read. assume you've read post mentioned , know how call system calls in x64 linux. assuming you're using nasm (or resembles syntax), , want store input stdin @ address buffer, have reserved bufsize bytes of memory, executing system call :

xor eax, eax ; rax <- 0 (write syscall number) xor edi, edi ; rdi <- 0 (stdin file descriptor) mov rsi, buffer ; rsi <- address of buffer mov edx, bufsize ; rdx <- size of buffer syscall ; execute 

upon returning, rax contain result of syscall. if want know more how works, please consult man 2 read.

parsing integer in assembly language not simple, though. since read gives plain binary data appears on standard input, need convert integer value yourself. keep in mind type on keyboard sent application ascii codes (or other encoding might using - i'm assuming ascii here). therefore, need convert data ascii-encoded decimal binary.

a function in c converting such structure normal unsigned int :

unsigned int parse_ascii_decimal(char *str,unsigned int strlen) {     unsigned int ret = 0, mul = 1;     int = strlen-1;     while(i >= 0)     {         ret += (str[i] & 0xf) * mul;         mul *= 10;         --i;     }     return ret; } 

converting assembly (and extending support signed numbers) left exercise reader. :)

last not least - write syscall requires pass pointer buffer data that's supposed written given file descriptor. therefore, if want output newline, there no other way create buffer containing newline sequence.


Comments

Popular posts from this blog

delphi - How to convert bitmaps to video? -

jasper reports - Fixed header in Excel using JasperReports -

python - ('The SQL contains 0 parameter markers, but 50 parameters were supplied', 'HY000') or TypeError: 'tuple' object is not callable -