Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; The OS/K Team licenses this file to you under the MIT license.
- ; See the LICENSE file in the project root for more information.
- _doprnt_test:
- mov ax0, .fmt
- sub rsp, 128
- mov q[rsp+40], 0x7FE
- mov q[rsp+32], -2
- mov q[rsp+24], 666
- mov q[rsp+16], 0x112233DDAA6677BB
- mov q[rsp+8], 'K'
- mov q[rsp], .str
- call printf
- add rsp, 128
- ret
- .fmt = "%% Hello World %s - %c - %p - %d - %d - %b"
- .str = "(cc)"
- ;
- ; typedef int (*PUTC)(int ch)
- ; int _doprnt(PUTC putc, int n, const char *fmt, va_list ap)
- ;
- _doprnt:
- enter 8
- mov q[rbp-8], rbx
- mov q[rbp-16], nx0
- mov q[rbp-24], nx1
- mov q[rbp-32], nx2
- mov q[rbp-40], rdi
- mov q[rbp-48], rsi
- mov q[rbp-56], nx3
- mov rbx, ax2 ; fmt
- mov nx3, ax0 ; putc
- mov nx0, ax1 ; n
- xor nx1, nx1 ; return value
- xor nx2, nx2 ; index in va_list
- mov rsi, ax3 ; ap
- .main_loop:
- ; find '%' or null-terminator
- mov rcx, STRLEN_MAX
- mov rdi, rbx
- scasb.rep.nz rdi, '%'
- .print_regular:
- ; everything below rdi is a regular character; print it
- cmp rbx, rdi
- j.z .check_modf
- mov ax0, b[rbx]
- call .doput
- inc rbx
- jmp .print_regular
- .check_modf:
- ; did we find a '%' ?
- cmp b[rbx], '%'
- j.nz .epilogue ; no, we found fmt's null-terminator; we're done
- ; we did find a modifier / '%'
- mov rax, b[rbx+1]
- add rbx, 2
- cmp rax, 's'
- j.z .modf_s
- cmp rax, 'c'
- j.z .modf_c
- cmp rax, 'p'
- j.z .modf_p
- cmp rax, 'x'
- j.z .modf_x
- cmp rax, 'u'
- j.z .modf_u
- cmp rax, 'd'
- j.z .modf_d
- cmp rax, 'o'
- j.z .modf_o
- cmp rax, 'b'
- j.z .modf_b
- cmp rax, '%'
- j.z .modf_percent
- ; unrecognized
- jmp .bad_modifier
- .modf_s:
- ; get string address
- mov rdi, q[rsi + nx2 * 8]
- inc nx2
- test rdi, rdi
- j.z .nullstring
- .print_string:
- mov ax0, b[rdi]
- test ax0, ax0
- j.z .main_loop
- inc rdi
- call .doput
- jmp .print_string
- .modf_c:
- mov ax0, q[rsi + nx2 * 8]
- inc nx2
- call .doput
- jmp .main_loop
- .modf_p:
- mov ax0, '0'
- call .doput
- mov ax0, 'x'
- call .doput
- ; Fallthrough
- .modf_x:
- mov ax2, 16
- mov ax3, 1
- jmp .print_number
- .modf_u:
- mov ax2, 10
- mov ax3, 1
- jmp .print_number
- .modf_d:
- mov ax2, 10
- xor ax3, ax3
- jmp .print_number
- .modf_o:
- mov ax2, 8
- mov ax3, 1
- jmp .print_number
- .modf_b:
- mov ax2, 2
- mov ax3, 1
- jmp .print_number
- .print_number:
- ; allocate itoa conversion buffer
- sub rsp, 80
- mov rdi, rsp
- ; assume modifier already set up ax2 and ax3
- mov ax0, rsp
- mov ax1, q[rsi + nx2 * 8]
- call _itoa
- inc nx2
- .print_itoa_buf:
- mov ax0, b[rdi]
- test ax0, ax0
- add.z rsp, 80
- j.z .main_loop
- inc rdi
- call .doput
- jmp .print_itoa_buf
- .modf_percent:
- mov ax0, '%'
- call .doput
- jmp .main_loop
- .bad_modifier:
- ; print "%?" to clearly indicate that something is wrong
- mov ax0, '$'
- call .doput
- mov ax0, '?'
- call .doput
- jmp .main_loop
- .nullstring:
- ; %s was passed a NULL
- mov ax0, '('
- call .doput
- mov ax0, 'n'
- call .doput
- mov ax0, 'u'
- call .doput
- mov ax0, 'l'
- call .doput
- mov ax0, 'l'
- call .doput
- mov ax0, ')'
- call .doput
- jmp .main_loop
- .epilogue:
- mov rax, nx1
- mov rbx, q[rbp-8]
- mov nx0, q[rbp-16]
- mov nx1, q[rbp-24]
- mov nx2, q[rbp-32]
- mov rdi, q[rbp-40]
- mov rsi, q[rbp-48]
- mov nx3, q[rbp-56]
- leave
- ret
- ;
- ; prints ax0
- ;
- .doput:
- ; update print count
- inc nx1
- ; if n==0, don't print
- ; we follow the C convention that sprintf()-like functions
- ; should return the number of characters that would have
- ; been printed/written if 'n' were big enough
- test nx0, nx0
- ret.z
- ; if n>0, decrement n and print
- dec nx0
- call nx3
- ; did putc fail?
- cmp rax, 0
- xor.nz nx0, nx0 ; yes, so artificially set n=0
- ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement