0

I am writing an assembly program in NASM and trying to write the value of 2 memory values to a file (specifically the value of varDD and varDW).

Unfortunately, I get a segmentation fault when trying to run it. Can anyone help identify the issue with this?

Please note that I'm not an assembly expert by any means so please forgive my ignorant mistakes.

section .data
        fileName db './output.txt', 0
        varDD dd 1.01, 0x00
        varDW dw 'abc', 0x00
        varDDL equ $ - varDD
        varDWL equ $ - varDW
section .text

        global  main


main:

        mov EAX, 8
        mov EBX, fileName
        mov ECX, 0700
        int 0x80
        mov EBX, EAX
        mov EAX, 4
        mov ECX, [varDD]
        mov EDX, [varDDL]
        int 0x80
        mov ECX, [varDW]
        mov EDX, [varDWL]
        int 0x80
        mov EAX, 6
        int 0x80
        mov eax, 1
        int 0x80

        mov eax, 60
        mov edi, 0
        syscall

Update: So I corrected to the following code:

section .data
        fileName db './output.txt', 0
        varDD dd 1.01, 0x00
        varDW dw 'abc', 0x00
        varDDL equ $ - varDD
        varDWL equ $ - varDW
section .text

        global  main


main:

        mov EAX, 8
        mov EBX, fileName
        mov ECX, 0700
        int 0x80
        mov EBX, EAX
        mov EAX, 4
        mov ECX, varDD
        mov EDX, varDDL
        int 0x80
        mov EAX, 4
        mov ECX, varDW
        mov EDX, varDWL
        int 0x80
        mov EAX, 6
        int 0x80
        mov eax, 1
        int 0x80

        mov eax, 1
        mov ebx, 0
        int 0x80

This does run and output a file but when viewing the hexdump of the file, the contents do not correspond to the hex values expected for the variables that were written.

Hex dump: 0000000 47ae 3f81 0000 0000 6261 0063 0000 6261 0000010 0063 0000 0000014

Update 2: I updated as follows:

section .data
        fileName db './output.txt', 0
        varDD dd 1.01, 0x00
        varDDL equ $ - varDD

        varDW dw 'abc', 0x00
        varDWL equ $ - varDW

The strace (relevant section) shows below:

creat("./output.txt", 01274)            = 3
write(3, "\256G\201?\0\0\0\0", 8)       = 8
write(3, "abc\0\0\0", 6)                = 6
close(3)                                = 0

I am supposed to use a hexdump to verify the values, but the hexdump still shows:

0000000 47ae 3f81 0000 0000 6261 0063 0000
000000e

That doesn't seem to correspond with the values that were written. 62 = b 61 = a and 63 = c .. those are out of order and I am not seeing the 1.01 value.

qscott86
  • 303
  • 3
  • 11
  • 1
    Many problems. `sys_write` expects a pointer not values but it does expect the value for the length but you try to dereference those as addresses (cause of the fault). You need to reload `eax` every time. Don't use `int 0x80` in 64 bit code. Learn to use a debugger and strace. – Jester Oct 10 '18 at 19:33
  • It's not 64 bit code – qscott86 Oct 10 '18 at 19:35
  • [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730), as well as your errors in doing loads instead of mov-immediate. – Peter Cordes Oct 10 '18 at 19:35
  • If it's not 64 bit code then the last 3 lines are wrong and the rest of the problems still applies. – Jester Oct 10 '18 at 19:36
  • @qscott86: Yes it is; `eax=60` / `syscall` only works in 64-bit code. If it's not supposed to be, then use the 32-bit ABI to call sys_exit. (Although it will assemble in 32-bit mode, because AMD did define a 32-bit version of the `syscall` instructions. It will fault on Intel CPUs though, if you run it in 32-bit mode and execution reaches it.) – Peter Cordes Oct 10 '18 at 19:36
  • Please see update above. – qscott86 Oct 10 '18 at 19:52
  • 1
    Use `strace ./a.out` to see exactly what each system-call wrote. – Peter Cordes Oct 10 '18 at 19:55
  • You also messed up the length `varDDL` as that should be before the `varDW`. The bytes are correct though, you just defined them in a somewhat unconventional way. – Jester Oct 10 '18 at 19:56
  • Oh, `varDDL equ $ - varDD` includes both `varDD` and `varDW`, because `$` at that point is the current position. [In NASM labels next to each other in memory are causing printing issues](https://stackoverflow.com/q/26897633) – Peter Cordes Oct 10 '18 at 19:57
  • I updated above – qscott86 Oct 10 '18 at 20:18
  • `1.01` is a single precision float you are not going to recognize it. See [wikipedia](https://en.wikipedia.org/wiki/Single-precision_floating-point_format) and [online converter](http://www.binaryconvert.com/result_float.html?decimal=049046048049). Your `abc` is messed up due to using `dw` and endianness. – Jester Oct 10 '18 at 20:24
  • You're hex dumping in little-endian 16-bit chunks. Use `hexdump -C` to get bytes. For the dword float, see https://en.wikipedia.org/wiki/Single-precision_floating-point_format – Peter Cordes Oct 10 '18 at 20:24
  • 1
    @Jester: `dw` doesn't munge multi-character constants (it just pads them to a multiple of 2 bytes). It's the 16-bit hexdump that's doing that. The `strace` output confirms it's fine. – Peter Cordes Oct 10 '18 at 20:25
  • Ok I think I got it now. Thank you all for your help! – qscott86 Oct 10 '18 at 20:27

0 Answers0