NASM - The Netwide Assembler

NASM Forum => Programming with NASM => Topic started by: proteusguy on October 11, 2017, 04:40:06 AM

Title: Newbie issue access STRUC members
Post by: proteusguy on October 11, 2017, 04:40:06 AM
Definitely has to be something stupid I'm missing but I can't get the correct value out of my CountedString.length as you can see from executing the code below. Appreciate any clues as to what I'm doing wrong as I've tried a dozen or so different things with no improvement.

Code: [Select]
struc CountedString
    .length: resb 1
    .str_ptr: resd 1
;    .ref_count: resw 1
    .counted_string_struc_size:
endstruc


global system_exit

    SECTION .text

system_exit:            ; terminates the running app cleanly.
    xor ebx,ebx         ; 0 is normal exit code for linux sys_exit call
    ;mov eax,1          ; sys_exit call id is 1
    xor eax,eax         ; xor then inc is one byte shorter than direct assignment of literal
    inc eax
    int 0x80            ; call linux kernel



global main

    SECTION .text
    startup_msg:    db "Test machine v 0.01 startup.", 10, 0
    startup_msg_len: equ $-startup_msg

startup_string:
        istruc CountedString
            at CountedString.length, db startup_msg_len
            at CountedString.str_ptr, dd startup_msg
 ;           at CountedString.ref_count, dw 0ffffh
        iend

main:
    ; print out our startup message then exit.

    mov edx, startup_msg_len
    mov ecx, startup_msg
    mov ebx, 1          ; stdout file handle
    mov eax, 4          ; sys_write call id
    int 0x80

   
    mov edx, startup_string + CountedString.length
    mov ecx, [startup_string + CountedString.str_ptr]
    mov ebx, 1          ; stdout file handle
    mov eax, 4          ; sys_write call id
    int 0x80

    call system_exit    ; exit application

In case it matters, I'm building this on NASM version 2.10.09 compiled on Dec 29 2013 under Kubuntu 14.04 using the following commands:
nasm -f elf64 -l machine_core.lst machine_core.asm
gcc -m64 -o machine machine_core.o

on a laptop with: uname -a
Linux satriani 4.4.0-97-generic #120~14.04.1-Ubuntu SMP Wed Sep 20 15:53:13 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
Title: Re: Newbie issue access STRUC members
Post by: Frank Kotler on October 11, 2017, 05:44:52 AM
Hi proteusguy,

Welcome to the forum.

There are a couple of issues here. Mainly, since you put the length in edx, it wants to be dword, not byte. Although the length would fit in a byte, by doing "mov edx..." we move four bytes - the length and the first three bytes of the string! Using "movzx edx, byte..." would also fix it.

Code: [Select]
; nasm -f elf32 this.asm
; ld -o this this.o -e main

struc CountedString
    .length: resd 1
    .str_ptr: resd 1
;    .ref_count: resw 1

; don't need this
    .counted_string_struc_size:
endstruc
; Nasm essentially does CountedString_size equ $ - CountedString
; don't need this since it's here - doesn't hurt
global system_exit

    SECTION .text

system_exit:            ; terminates the running app cleanly.
    xor ebx,ebx         ; 0 is normal exit code for linux sys_exit call
    ;mov eax,1          ; sys_exit call id is 1
    xor eax,eax         ; xor then inc is one byte shorter than direct assignment of literal
    inc eax
    int 0x80            ; call linux kernel


; ask nasm to tell linker about this entrypoint
global main

section .data
;    SECTION .text

; don't need the terminating zero - doesn't hurt
    startup_msg:    db "Test machine v 0.01 startup.", 10, 0
    startup_msg_len: equ $-startup_msg

startup_string:
        istruc CountedString
            at CountedString.length, dd startup_msg_len
            at CountedString.str_ptr, dd startup_msg
 ;           at CountedString.ref_count, dw 0ffffh
        iend

section .text
main:
    ; print out our startup message then exit.

    mov edx, startup_msg_len
    mov ecx, startup_msg
    mov ebx, 1          ; stdout file handle
    mov eax, 4          ; sys_write call id
    int 0x80

   
    mov edx, [startup_string + CountedString.length]
    mov ecx, [startup_string + CountedString.str_ptr]
    mov ebx, 1          ; stdout file handle
    mov eax, 4          ; sys_write call id
    int 0x80

    call system_exit    ; exit application

There are a couple trivial issues... "main" is known to the C language as the entrypoint. If you're using gcc, this is right. Since we have no C code here, we don't need to use gcc - although we can. I chose to link it directly with ld. ld knows "_start:" as the default entrypoint. We can tell it something else with the "-e" switch. Normally I would probably use "_start:", but for no good reason I used "-e main".

You also need the square brackets around the length. If we use "equ" it's an immediate number so no [] needed. But if we use "dd", as in the structure, it's a memory variable and we need 'em.

You've got the "struc" thing pretty well, it was these other issues that were giving you trouble.

Best,
Frank

Title: Re: Newbie issue access STRUC members
Post by: proteusguy on October 12, 2017, 05:46:42 PM
Frank,

    Thanks much for the help! I knew it was something simple. However I don't feel quite so bad as I still can't find anything in the documentation that would have gotten me a valid syntax. To wit - ultimately I need that CountedString.length to be 8-bits so your suggestion to use movzx was what I needed. Now - getting the movzx syntax correct was troublesome but I found some examples on the interweb that made me finally try this:

Code: [Select]
movzx edx, byte [startup_string + CountedString.length]

Now I can't find any nasm docs on that "byte" specification which was the final missing link. Did I miss something or is there a secret syntax reference out there? Anyway - appreciate your advice and patience! I can use STRUC now!
Title: Re: Newbie issue access STRUC members
Post by: Frank Kotler on October 12, 2017, 07:27:02 PM
That's a good question! Nasm sometimes needs a "size specifier" - byte/word/dword/qword. For example:
Code: [Select]
mov [myvar], 42]
won't assemble. Nasm doesn't know what size of 42 we need, We need to do:
Code: [Select]
mov byte [myvar], 42
;or
mov [myvar], byte 42

Some time ago, there was a question here as to which was the preferred position for the size specifier. Either will work, in this case, but "movzx" (etc.) requires it to be with the source operand. I suggested that he might want to always put it with the source operand for consistency ( although I often don't do it). It must say that somewhere in the Manual, but I can't find it at the moment. I'll look some more...

When I wrote my last reply, I missed the fact that you were doing 64 bit code (and that you were, in fact, using gcc). What you've got there is 32 bit code. It will work, within limits, but if you want 64 bit code, you might want to use 64 bit system call numbers (they are different), put the parameters in 64 bit registers (they are different), and use "syscall" instead of "int 0x80". I'm still running a 32 bit machine, so I can't help you too much with that. Accessing the structure elements should be the same.

Best,
Frank