2

I'm trying to run the code presented in tanenbaum computer architecture 6th book. I typed exactly the same code as the book. here is the code:

        .686
.MODEL FLAT
PUBLIC _towers
EXTERN _printf:NEAR
.CODE
_towers:
    push ebp
    mov ebp, esp
    cmp [ebp + 8], 1
    jne L1
    mov eax, [ebp + 16]
    push eax
    mov eax, [ebp + 12]
    push eax
    push OFFSET FLAT:format
    call _printf
    add esp, 12
    jmp Done
    mov eax, 6
    jmp Done
L1:
    mov eax, 6
    sub eax, [ebp + 12]
    sub eax, [ebp + 16]
    mov [ebp + 20], eax
    push eax
    mov eax, [ebp + 12]
    push eax
    mov eax, [ebp + 8]
    dec eax
    push eax
    call _towers
    add esp, 12
    mov eax, [ebp + 16]
    push eax
    mov eax, [ebp + 12]
    push eax
    push 1
    call _towers
    add esp, 12
    call _towers
    add esp, 12
    mov eax, [ebp + 12]
    push eax
    mov eax, [ebp + 20]
    push eax
    mov eax, [ebp + 8]
    dec eax
    push eax
    call _towers
    add esp, 12
Done:
    leave
    ret 0
.data
    format db "Move disk from %d to %d\n"
END 

But it has some errors:

Hanoi.asm:2: error: attempt to define a local label before any non-local labels
Hanoi.asm:3: error: attempt to define a local label before any non-local labels
Hanoi.asm:3: error: parser: instruction expected
Hanoi.asm:4: error: parser: instruction expected
Hanoi.asm:5: error: no special symbol features supported here
Hanoi.asm:16: error: comma, colon, decorator or end of line expected after operand

I'm totally new to this language. I'm using NASM as the assembler on x86_68 linux ubuntu like:

nasm -f elf64 -o Hanoi.o Hanoi.asm
fuz
  • 88,405
  • 25
  • 200
  • 352
Kasra GH
  • 157
  • 2
  • 5
  • 22
  • Please paste the code into the question. Questions must be self-contained. – fuz Nov 15 '17 at 14:40
  • Note that this is 32 bit assembly, so you should use `-f elf` to assemble it. – fuz Nov 15 '17 at 14:41
  • Furthermore, this program is neither made to be assembled with nasm, nor will it run on Linux without slight modifications due to the lack of symbol decorations on ELF targets. If you like, I can do the modifications needed to get this to run and write this up as an answer. – fuz Nov 15 '17 at 14:43
  • @fuz I tried the command with "-f elf' too put it produces exactly the same errors. – Kasra GH Nov 15 '17 at 14:43
  • That's because there are other things wrong, too, with your program. Please first paste the code into the question so I can go on and continue helping you. – fuz Nov 15 '17 at 14:44
  • @fuz I've modified the code [link](https://github.com/ghasemikasra39/Testing/blob/master/Hanoi2.asm) to address some problems. the only error is now this: Hanoi.asm:24: error: comma, colon, decorator or end of line expected after operand – Kasra GH Nov 15 '17 at 14:48
  • @fuz Would it be alright if I didn't past the code here because it's going to be much more harder for you to find the errors since there would be no line number – Kasra GH Nov 15 '17 at 14:50
  • Questions on Stack Overflow must be self contained. If you don't post the code in your question, your question is going to be removed. Line numbers are not important (also, please don't add any when posting the code). I can just cite a line when I want to point out an error. – fuz Nov 15 '17 at 14:52
  • @fuz You're right. I edited the post. Now it has the code. – Kasra GH Nov 15 '17 at 14:55

1 Answers1

1

nasm has slightly different syntax than whatever assembler this was created with, so the following changes must be made:

nasm doesn't need any of these directives, so remove them:

END
.686
.MODEL FLAT

The first directive instructs the assembler to end assembling, this is done implicitly in nasm when the file ends, so the directive is not needed. .686 selects an instruction set, again unneeded in nasm. .MODEL FLAT selects the flat model, which is always the case in nasm (nasm doesn't support other models), so get rid of it too.

In nasm, PUBLIC is spelled GLOBAL, .CODE and .DATA are spelled section .text and section .data. Furthermore, qualifiers such as NEAR or FAR are not needed as nasm doesn't know segmentation. The offset keyword needs to be removed, too. nasm distinguishes memory operands from immediates using brackets, an operand foo is always seen as an immediate regardless of type. To make it a memory operand, you need to write [foo].

The instruction

 cmp [ebp + 8], 1

lacks a size qualifier. Fix this by adding DWORD:

cmp dword [ebp + 8], 1

Another thing you need to fix is the symbol decoration. On Windows, C functions are decorated with a leading underscore. This is not the case on Linux, so just remove all the underscores so your code links correctly. As a result of this, you need to prepend . to all local symbols as without a leading underscore, they cannot be distinguished from external symbols. The resulting program looks like this:

    global towers
    extern printf

    section .text

towers:
    push ebp
    mov ebp, esp
    cmp dword [ebp + 8], 1
    jne .L1
    mov eax, [ebp + 16]
    push eax
    mov eax, [ebp + 12]
    push eax
    push .format
    call printf
    add esp, 12
    jmp .Done
    mov eax, 6
    jmp .Done
.L1:
    mov eax, 6
    sub eax, [ebp + 12]
    sub eax, [ebp + 16]
    mov [ebp + 20], eax
    push eax
    mov eax, [ebp + 12]
    push eax
    mov eax, [ebp + 8]
    dec eax
    push eax
    call towers
    add esp, 12
    mov eax, [ebp + 16]
    push eax
    mov eax, [ebp + 12]
    push eax
    push 1
    call towers
    add esp, 12
    call towers
    add esp, 12
    mov eax, [ebp + 12]
    push eax
    mov eax, [ebp + 20]
    push eax
    mov eax, [ebp + 8]
    dec eax
    push eax
    call towers
    add esp, 12
.Done:
    leave
    ret 0

    section .data

.format db "Move disk from %d to %d\n"

and assembles with

nasm -f elf Hanoi.asm

Note that because this is clearly meant to be 32 bit code, -f elf instead of -f elf64 is needed.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • Now the code is error-free. The next step is to create an executable using _ld_ command like : **ld Hanoi.o -o Hanoi**. There're some errors here: ld: i386 architecture of input file `Hanoi.o' is incompatible with i386:x86-64 output ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0 Hanoi.o: In function `towers': Hanoi.asm:(.text+0x17): undefined reference to `printf' – Kasra GH Nov 15 '17 at 15:23
  • @KasraGH You need to specify 32 bit output and link in the libc. I recommend you to link with the C compiler like this: `cc -m32 -o Hanoi Hanoi.o`. Note that as it doesn't have a main function, your code won't link as is. `towers` seems to take arguments, a separate `main` function seems to be needed. – fuz Nov 15 '17 at 15:27
  • I used _ld -m elf_i386 -s -o file.o file_ . Now the only error is: Hanoi.o: In function `_start': Hanoi.asm:(.text+0x17): undefined reference to `printf – Kasra GH Nov 15 '17 at 15:34
  • 1
    @KasraGH You need to link the libc. Pass `-lc` as the last argument to the linker. Note that this might not work as linking directly with `ld` omits the library initialisation stub inserted by the C compiler when linking. I strongly recommend you to use the C compiler to link your program if you are using libc functions. – fuz Nov 15 '17 at 15:38
  • I used this ld -m elf_i386 -e towers -dynamic-linker /lib/ld-linux.so.2 -o Hanoi Hanoi.o -lc and the executable created successfully. When I run the executable the output is : Segmentation fault (core dumped) I run the executable like ./Hanoi – Kasra GH Nov 15 '17 at 15:53
  • 1
    @KasraGH: Unless you have some other bug, that's because you tried to `ret` from the ELF entry point (`-e towers`) instead of using `sys_exit`. You can't do that on Linux (and it's not safe anymore on Windows). If you just followed @ fuz's suggestion to write a `main()` function that calls `towers()` with args and build with `cc -m32 -o Hanoi Hanoi.o`, you'd already have solved your problem. (And yes, you use `cc` / `gcc` to invoke `ld` for you to make sure libc is initialized correctly before your code runs. But in practice dynamically linking will initialize libc correctly.) – Peter Cordes Nov 15 '17 at 16:08
  • @PeterCordes would it be alright if you wrote the correct syntax of function declaration that accept an argument as well as calling that function with argument ? – Kasra GH Nov 15 '17 at 16:13
  • 1
    @KasraGH Its C prototype is something like `int towers(int depth, int unknown, int unknown);`. You could call it from C with `int main(){ towers(3, 4, 5); }`. I didn't reverse-engineer the whole function to see what the 2nd two args do, but the first one is the one that stops the recursion. Doesn't your book tell you how to call it, or say something about how it works? – Peter Cordes Nov 15 '17 at 16:19
  • @PeterCordes the output is /usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32/crt1.o: In function `_start': (.text+0x18): undefined reference to `main' collect2: error: ld returned 1 exit status – Kasra GH Nov 15 '17 at 16:26
  • @Kasra GH where is your `main` function? Did you link its object in? – fuz Nov 15 '17 at 16:27
  • @KasraGH: That's because you didn't include the `main()` function I showed in a `main.c`. You could also have written it in asm, but writing it in C is easier. – Peter Cordes Nov 15 '17 at 16:27
  • @PeterCordes I edited the code as you said like [this](https://github.com/ghasemikasra39/Testing/blob/master/Hanoi3.asm) and run the command like : cc -m32 -o Hanoi.o Hanoi – Kasra GH Nov 15 '17 at 16:31
  • @KasraGH: you can't mix asm and C in the same file. Put main in a separate file and run `gcc -m32 -g main.c Hanoi.o -o Hanoi`. – Peter Cordes Nov 15 '17 at 16:36
  • @PeterCordes I did it. the output is : main.c: In function ‘main’: main.c:1:13: warning: implicit declaration of function ‘towers’ [-Wimplicit-function-declaration] int main(){ towers(3, 4, 5); } [this](https://github.com/ghasemikasra39/Testing/blob/master/main.c) is main.c and [this](https://github.com/ghasemikasra39/Testing/blob/master/Hanoi5.asm) is Hanoi.asm (I uesd nasm -f elf -o Hanoi.o Hanoi.asm to create Hanoi.o) – Kasra GH Nov 15 '17 at 16:46
  • 1
    @Kasra GH Now link and run that. Note that its very hard to help you if you don't follow the instructions you get. I think the book should explain all of this somewhere. Have you tried just reading on? It seems strange that this hanoi example comes without the rest of the program (i.e. main) and without any instructions. – fuz Nov 15 '17 at 16:50
  • @fuz it gives the same result : Segmentation fault (core dumped) . I read the book. There was only this code and nothing else – Kasra GH Nov 15 '17 at 16:57
  • @KasraGH It seems that the program has a bug somewhere. I get the same result on my machine. I suppose there is a typo somewhere. Debugging this is probably a good exercise. – fuz Nov 15 '17 at 18:01