Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

assembly - db usage in nasm, try to store and print string

I was trying to store a few strings in my assembly, and use WriteString to print out on the screen. However, I only call one of the strings, it shows up all of them in one single line. Why does this happen? Is that anything wrong in my code? Thanks!

Code here:

%include "lib/libasm.h"
SECTION .text

global main

main:
    call badrng
    ret 


badrng:
    push eax
  push edx
    mov edx, badrngstr
    call WriteString
    pop edx
    pop eax
    call failure
    ret

failure:
    mov  eax,1
    int  0x80
    ret


SECTION .data
nlstr:      db ""
badrngstr:  db "Value out of range in assignment"
baddivstr:  db "Division by zero"
badcasstr:  db "Value not handled in case statement"
badptrstr:  db "Attempt to use a null pointer"
badsubstr:  db "Subscript out of bounds"
stkovstr:   db "Stack overflow"
heapovstr:  db "Out of heap space"

and WriteString is in libasm.s

    EXTERN  main

    SECTION .text
    GLOBAL  _start
_start:
    call    main
    mov ebx, eax
    call    Exit
    ret

    GLOBAL  AsciiDigit
AsciiDigit: ; al = digit to convert
    SECTION .data
.xtable db  "0123456789abcdef"
    SECTION .text
    push    ebx
    mov ebx, .xtable
    xlat
    pop ebx
    ret

    GLOBAL  Crlf
Crlf:
    SECTION .data
.lf db  0x0a
.lflen  equ $-.lf
    SECTION .text
    pusha
    mov ecx, .lf
    mov edx, .lflen
    call    Write
    popa
    ret

    GLOBAL  Exit
Exit:                   ; ebx = error code
    mov eax, 0x01
    int 0x80
    ret

    GLOBAL  Strlen
Strlen:                 ; edi = string
    push    edi
    mov eax, 0
.L1:
    cmp byte [edi], 0       ; end of string?
    je  .L2
    inc edi
    inc eax
    jmp .L1
.L2:
    pop edi
    ret

    GLOBAL  Write
Write:                  ; ecx = buffer, edx = count
    push    ebx
    mov eax, 0x04       ; sys_write = 4
    mov ebx, 1          ; fd = 1 (stdout)
    int 0x80
    pop ebx
    ret

    GLOBAL  WriteChar
WriteChar:              ; al = the char
    SECTION .data
.bb db  0
    SECTION .text
    pushad
    mov byte [.bb], al
    mov ecx, .bb
    mov edx, 1
    call    Write
    popad
    ret

    GLOBAL  WriteHex
WriteHex:               ; eax = the number
    SECTION .data
.buf    TIMES 16 db 0           ; buffer
.bufsz  equ $-.buf          ; bufsize
    SECTION .text
    pushad
    mov edi, .buf       ; point to the string
    add edi, .bufsz
    mov ecx, 0          ; buflen
.L1:
    mov ebx, eax        ; preserv eax into ebx
    and al, 0x0f
    call    AsciiDigit
    dec edi
    mov byte [edi], al
    inc ecx
    mov eax, ebx        ; restore eax
    shr eax, 4
    or  eax, eax        ; eax == zero ?
    jnz .L1
    ;
    mov edx, ecx
    mov ecx, edi
    call    Write
    popad
    ret

    GLOBAL  WriteInt
WriteInt:               ; eax = the number
    SECTION .data
.isneg  db  0           ; negative = 0 (false)
.buf    TIMES 16 db 0           ; buffer
.bufsz  equ $-.buf          ; bufsize
    SECTION .text
    pushad
    mov byte [.isneg], 0    ; negative = 0 (false)
    or  eax, eax        ; eax is positive?
    jns .L1
    neg eax
    mov byte [.isneg], 1    ; negative = 1 (true)
.L1:
    mov edi, .buf       ; point to the string
    add edi, .bufsz
    mov ecx, 0          ; buflen
    mov ebx, 10         ; divided by 10
.L2:
    mov edx, 0          ; edx:eax = the number
    div ebx         ; eax = Q, edx = R
    or  dl, 0x30        ; convert value to ASCII
    dec edi
    mov byte [edi], dl
    inc ecx
    or  eax, eax        ; eax == zero ?
    jnz .L2
    ; add the sign symbol
    cmp byte [.isneg], 0
    je  .L3
    dec edi
    mov byte [edi], '-'
    inc ecx
.L3:
    mov edx, ecx
    mov ecx, edi
    call    Write
    popad
    ret

    GLOBAL  WriteString
WriteString:
    SECTION .text
    pushad
    mov edi, edx
    call    Strlen
    mov ecx, edx
    mov edx, eax
    call    Write
    popad
    ret

and output result is

Value out of range in assignmentDivision by zeroValue not handled in case statementAttempt to use a null pointerSubscript out of boundsStack overflowOut of heap space

I don't know why it would print all the string out, even though I only move one string the edx. Please, can anyone tell where did I do wrong?

Note: It is tested and run on ubuntu 12.04 32bit.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The strings have to be null terminated -- you have to indicate the zero value for the last byte. You may also need to indicate carriage returns and line feeds if you want the output routine to put the string on it's own line.

You do this by specifying:

nullstr db 0
errorMessage db 'critical error', 10, 13, 0
warningMessage db 'warning', 10, 13, 0

goodbyeWorld1 db 'Goodbye World.', 0
goodbyeWorld2 db 'Goodbye World.'

endline db 10, 13, 0

The endline string would work on the principle that since goodbyeWorld2 is not null terminated, it would display the ascii codes for carriage feed and line return, so Goodbye World. would appear on it's own line in the shell output. However since goodByeWorld1 is null-terminated it would not appear on it's own line and output would continue at the final '.' character displayed.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...