0

So in the code below, I am attempting to print just the good bye message but all 3 get printed and if a 4 variable is added, it get printed as well . What could be causing this and how can I fix it.

I have read some posts which suggest something about a null terminator however using

goodbyeMsg db " powering off",0

goodbyeMsg db " powering off$",10, 13, 0

goodbyeMsg db " powering off",10, 13, 0
goodbyeMsg db " powering off$"

did not work

the sample code:

section .text
    global _start

    _start:
        mov eax,4
        mov ebx,1
        mov ecx,goodbyeMsg
        mov edx,lenGoodbyeMsg
        int 80h

        mov eax, 1
        mov ebx ,0
        int 80h

section .data
    welcomeMsg db "Welcome, to Ugo Air Condition"
    lenWelcomeMsg db $-lenWelcomeMsg
    goodbyeMsg db " powering off"
    lenGoodbyeMsg  db $-lenGoodbyeMsg
    help db "enter q w e r t y u "
    lenHelp   db  $-lenHelp
    quitKey db "q"
    lenQuitKey equ $ - quitKey
    defaultMode db "Stationary"
    lenDefaultMode equ $-defaultMode

    defaultTemp db 18
    defaultFanSpeed db 2


section .bss
    userInput resb 10
    powerState resb 10
    currentTemp resb 10
    currentMode resb 10
    currentFanSpeed resb 10

the output:

powering offenter q w e r t y u qStationarys

the result of strace

execve("./air", ["./air"], [/* 58 vars */]) = 0
[ Process PID=5169 runs in 32 bit mode. ]
enter q w e r t y u qStationary) = 2048 "..., 134516943 powering off
_exit(0)                                = ?
+++ exited with 0 +++
uhexos
  • 383
  • 4
  • 19
  • Because you defined the end of all your strings in the same place? Move the length definitions to the end of the appropriate strings. – Jester Feb 06 '18 at 14:22
  • the `$` is "current" line – Ped7g Feb 06 '18 at 14:36
  • I.e. the way you wrote it, you would have to do `len equ msg1 - msg` `len1 equ msg2 - msg1` `len2 equ $ - msg2` ... or move the length definitions right after the particular string, then you can use special symbol `$` for each "end of string" address. – Ped7g Feb 06 '18 at 14:52
  • Thanks for the quick answer but i have edited the question since the proposed solution didn't solve the problem when applied to my actual code – uhexos Feb 06 '18 at 18:01
  • Use `strace ./air > /dev/null` to avoid mixing the trace with the regular stdout. It looks like there was probably a `write` system call that returned `2048`, but a carriage return somewhere seems to have overwritten the trace output for it. – Peter Cordes Feb 06 '18 at 18:49

2 Answers2

2

lenGoodbyeMsg db $-lenGoodbyeMsg emits one byte in the data section, with value 0 (because you use lenGoodbyeMsg instead of goodbyeMsg).

It's followed in the data section by the ASCII codes for e, n, and t, from the start of the data following the help: label. If you had loaded a dword from lenGoodbyeMsg, you would have gotten a very large number.


But none of that data even matters, because mov edx,lenGoodbyeMsg puts the address of the lenGoodbyeMsg label into edx, and that large number becomes the length arg to sys_write. If you ran your program under strace, you'd see a very large length being passed to sys_write. It's a bit surprising that sys_write doesn't just fail with -EFAULT without printing anything; I guess it's printing the first page before detecting the fault?

(Or else you didn't update the question after rewriting your code, which was initially a duplicate of In NASM labels next to each other in memory are causing printing issues.)


mov edx,lenGoodbyeMsg would be the right instruction if you'd written
lenGoodbyeMsg equ $ - goodbyeMsg instead of db, like every working example of getting the assembler to calculate lengths for you. Because then lenGoodbyeMsg would be an assembler constant, not an address.

See How does $ work in NASM, exactly? for more details.


Of course null terminators didn't work: you're using sys_write which takes a pointer + length and works on arbitrary binary data.

C library functions like puts / printf / strstr take null terminated implicit-length strings.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • thanks for the reply , but after fixing those errors, I still got the same error only without the powering off output: enter q w e r t y u qStationarys – uhexos Feb 06 '18 at 18:21
  • @uhexos: What does `strace` say you're passing as args to `sys_write`? Are you sure you replaced all the `db` lines with `lenGoodbyeMsg equ $ - goodbyeMsg` or the equivalent for other messages? – Peter Cordes Feb 06 '18 at 18:23
  • honestly I just started assembly like a week ago and have no background in c, so could you please explain what you mean by strace, Yes I have replaced all db line appropriately and can update my question with a newer version if it would help – uhexos Feb 06 '18 at 18:29
  • @uhexos: Run `strace ./my_program` to print a trace of all the system calls it makes. Google would have told you that. And sure, add a new section to your question with your new version if you want. – Peter Cordes Feb 06 '18 at 18:29
  • @uhexos: put the strace log in your question, where you can use code formatting. Because you left out the actual `write()` call. Or try using `strace ./air > /dev/null` so *only* the trace shows in your terminal, not the regular output. Or use `strace -o foo.trace ./air` to log to a file instead of the terminal, so the trace is again separated from the regular stdout. (Probably there was a carriage return somewhere in the non-ASCII garbage bytes you're printing out by passing too large a length, so the `write( ...` stuff on your terminal is overwritten). – Peter Cordes Feb 06 '18 at 18:41
  • sys_write does not care about the NUL-character, so you just could obmit it. It only matters in the sys_open-syscall, because file names are expected to have a NUL-character at the end. – sivizius Feb 06 '18 at 19:07
0

The problem comes from the db written in the .data section. Changing them to equ fixed my problem. Thanks just for the help everyone.

uhexos
  • 383
  • 4
  • 19