2014-09-13 10 views
0

나는 64 비트 어셈블리 코드 (yasm)에서 임의로 큰 십진수 값을 출력하여 올바르게 읽고 이상하게 읽거나 한 자릿수로 읽지 않으려 고 노력하고 있습니다. 주변을 둘러 보았지만 온라인에서 적합한 솔루션을 찾을 수없는 것 같습니다. 내 코드는 현재 2 값 10 진수 숫자를 출력합니다 (출력 몫, 10으로 나눈 나머지를 출력). 더 큰 값을 위해 나는 반복적으로 10으로 나누어서 나머지를 출력하는 반면에 나머지는 0이 아닌 do-while 루프 구성 라인을 생각하고있었습니다. 이 방법의 문제점은 결과를 역으로 출력하므로 코드를 복잡하게 추가하여이를 시도하고이를 역전시킬 수 있다는 것입니다. 누구든지 작동 할 해결책을 알고 있습니까? 나는 aaa, aam 등을 살펴 봤지만 어떻게 작동하는지 완전히 알 수는 없으며 32 비트 연산에서만 사용할 수 있다고 생각합니다. 다음어셈블러에서 출력을위한 십진수 값 변환

코드 구조는 다음

section .data 
    nl db "",2,0 
    nlf db "",10,0 
    input db '',2,0 
    fact dq 1 
    y db 10 
    store dq 0 
    rem dq 0 
    quot dq 0 
    check dq 0 

section .text 
    global _start  

_start:   

; reading input value 
    mov rax, 0  ; system read 
    mov rdi, 0  ; STD IN 
    mov rsi, input ; address first byte in output 
    mov rdx, 1  ; load length into rdx 
    syscall 

    ; reading newline 
    mov rax, 0  ; system read 
    mov rdi, 0  ; STD IN 
    mov rsi, nl  ; address first byte in output 
    mov rdx, 1  ; load length into rdx 
    syscall 

    mov rbx, [input]  ; for calculating factorial 
    sub rbx, '0' 
    call calc_fact 
    call de_ASCII_fy 

    ;add rax, 30h 

    mov rax, 1   
    mov rdi, 1   
    mov rsi, nlf  
    mov rdx, 1   
    syscall 

    ; exit 
    xor rdi, rdi 
    push 0x3c 
    pop rax 
    syscall 

    calc_fact: 
     cmp bl, 1 
     jg do_calculation 
     mov rax, 1 
     ret 

    do_calculation: 
     dec bl 
     call calc_fact 
     inc bl 
     mul bl   
     ret 

    de_ASCII_fy: 
     mov [fact], rax 
     movzx rax, byte [fact] 
     cmp rax, 0 
     je decimal_loop 
     movzx rbx, byte [y] 
     xor rdx, rdx 
     div rbx 
     xor rcx, rcx 
     mov rcx, rdx ; store remainder 
     add rax, '0' 
     add rdx, '0' 
     mov [rem], rdx 
     mov [quot], rax 
     cmp rcx, 0 
     jnz full_print 
      mov rax, 1  ; system write 
      mov rdi, 1  
      mov rsi, rem  
      mov rdx, 1 
      syscall 
      ret 
      full_print: 
      mov rax, 1  ; system write 
      mov rdi, 1  
      mov rsi, quot 
      mov rdx, 1  
      syscall 
      mov rax, 1  ; system write 
      mov rdi, 1  
      mov rsi, rem  
      mov rdx, 1 
      syscall 
      jmp endif 
     endif:ret 
     decimal_loop: 
     ret 

I 4에 대한 출력을 표시하려고 계승 값을 산출하고! 24와 5로! 이제는 2 개의 10 진수 값만 표시 할 수 있습니다 (어떤 이유로 full_print 조건의 첫 번째 부분이 건너 뜁니다. 3!이 6 대신 06으로 인쇄됩니다). 그러나 24가 올바르게 인쇄됩니다. 나는 뇌에 3 자리 10 진수 값을 인쇄하는 간단한 방법을 고수했다. 그러나 조건문이 매우 엉망이되기 시작한다.

+2

첫 번째 방법이 가장 일반적입니다. 나머지를 첫 번째 루프의 스택에'push '하고 두 번째 루프에'pop'을 인쇄/저장 할 수 있습니다. 스택이 LIFO 메모리로 구성되어 있기 때문에 쉽게 역순으로 숫자를 가져올 수 있습니다. – rkhb

+0

몇 가지 코드를 보여줄 수 있습니까? –

답변

1

이 예를 살펴 : BTW

global _start 

section .bss 
    decimal resb 32 

section .data 

    number dq 10000000000000000000 
    lf db 10 

section .text 

_start: 
    mov rdi, decimal 
    mov rsi, [number] 
    call IntegerToDecimal 

    mov eax, 1  ; sys_write 
    mov edi, 1  ; STDOUT 
    mov rsi, decimal ; String address 
    mov edx, 32  ; Max. string length 
    syscall 

    mov eax, 1  ; sys_write 
    mov edi, 1  ; STDOUT 
    mov rsi, lf  ; Line Feed address 
    mov edx, 1  ; Max. string length 
    syscall 

    mov eax, 60   ; sys_exit 
    xor edi, edi  ; return 0 (success) 
    syscall 

IntegerToDecimal: 
    mov rax, rsi 
    mov ebx, 10   ; Divisor 
    xor ecx, ecx  ; RCX=0 (Anzahl der Ziffern) 
    .Loop_1: 
    xor edx, edx 
    div rbx    ; RDX:RAX/RBX = RAX Remainder RDX 
    push dx    ; LIFO 
    add cl, 1 
    or rax, rax  ; RAX == 0? 
    jnz .Loop_1   ; no: once more 
    .Loop_2: 
    pop ax    ; Get back pushed digits 
    or al, 00110000b ; Convert to ASCII 
    mov [rdi], al  ; Store character 
    add rdi, 1   ; Increment target address 
    loop .Loop_2  ; Until there are no digits left 
    mov byte [rdi], 0 ; ASCIIZ-null-terminator 

    ret 

: 나는 OS (Windows 또는 Linux) 및 조립 스타일 (NASM 또는 가스)를 알았다면 당신은, 어제의 예를 가지고 있었다. ;-)

+0

정말 고마워요. 이제는 출력물을 얻었지만 원본 코드에서 해결해야 할 오버플로 문제가 있음을 알 수 있습니다. 저는 어셈블리 코드에 익숙하지 않고 어둠 속에서 구조와 기법의 논리를 C++과 Java에서 매우 간단하게 어셈블리로 변환하는 것에 대해 말을 겁니다. 그것은 다른 사람들이 어떻게 코드 하는지를 볼 수있는 데 정말로 도움이됩니다. – user2781042