0

I'm using SASM editor for assembler. And I use PRINT_DEC from "io.inc" library to print. And here is the problem:

%include "io.inc" 

section .text
global main
main:
    mov eax, 0
    mov ah, 1
    PRINT_DEC 2, ah
    xor eax, eax
    ret

The ah register is 1 byte, but I print 2 bytes of it, it works ok, but I want to understand where does the extra byte get from

And when I put number 1 in al register like this:

main:
    mov eax, 0
    mov al, 1
    mov ah, 1
    PRINT_DEC 2, ah
    xor eax, eax
    ret

It prints 1 again. So the extra byte is not reading from al (the right byte of ah)

Then I tried to put number 1 in 16th bit of eax (left byte of ah) like this:

main:
    mov eax, 0x100000
    mov ah, 1

    PRINT_DEC 2, ah
    xor eax, eax
    ret

It prints the number 1 again, the extra byte is not from left side either.

So the question is, where is that extra byte printing from.

P.S. It is my university homework, so I need to know exact answer with explanation :)

Yespa16
  • 51
  • 4
  • What `io.inc` library? Where did that library come from, does it come with SASM? Obviously the answer is in its code, in how that macro expands, so look at its source or disassemble your program that uses it. Does it push the containing register, or does it store it to a buffer that might contain garbage? Or zero-extend to a wider register and convert integer to ASCII string? What output do you actually get on stdout; I'm guessing it's ASCII text, not a byte with integer value `1`? Is there a newline? – Peter Cordes Feb 19 '23 at 08:16
  • `mov eax, 0x100000` sets EAX to `1<<20` not `1<<16`. Even `1<<16` would be the byte above (left of) AH. I think you mean "byte left of AH", since "left byte of AH" implies that AH has multiple bytes and you're talking about the left-most. But actually you mean the byte next to AH, to the left. The English phrasing for that is "byte left of AH". But anyway, you did successfully set the byte above AH to a non-zero value, to `0x10` instead of `0x01`. You could have just done `mov eax, 0x100100` to put the same value in EAX before `PRINT_DEC`. – Peter Cordes Feb 19 '23 at 08:23
  • Another way to see what the macro does would be to single-step with a debugger. (Use disassembly mode if source-line mode gets weird because it's a macro.) e.g. in GDB, `layout asm`. Or `layout reg` / `layout next` to see register + disassembly. See the bottom of https://stackoverflow.com/tags/x86/info for asm debugging tips. Using a debugger is an essential tool for seeing what happens when you run a program, and for learning asm in general. – Peter Cordes Feb 19 '23 at 08:24
  • I'm looking to the source code right now, but it's hard to understand it. Can I somehow convert assembly code to C? By the way here is the source code. https://github.com/Dman95/SASM/blob/master/BSD/share/sasm/include/io.inc – Yespa16 Feb 19 '23 at 08:38
  • And answering your question. There is no newline in stdout. – Yespa16 Feb 19 '23 at 08:39
  • 1
    The first parameter (size) only really applies if the second parameter is a memory address or a constant. If the first parameter is a register the size is essentially irrelevant. If you specify a register the size is implied by the register itself. – Michael Petch Feb 19 '23 at 09:02
  • So, if the second parameter is a register, it prints only the value of that register? In this case only AH, one byte? – Yespa16 Feb 19 '23 at 09:05
  • Yes, that is correct @Yespa16 – Michael Petch Feb 19 '23 at 09:06
  • Ok, so the source defines it in terms of other macros. So that's complicated to wade through, much easier to just look at how it assembles, like with `nasm -felf32 -l /dev/stdout foo.asm` to see a listing which might show macro names recursively, and/or disassembly or single-step debugging like I mentioned as a way to see the actual instructions. But note that `PRINT_DEC` itself passes `movsx` as one of the macro parameters to another macro, so right away I can guess it's going to sign-extend narrow args with that. – Peter Cordes Feb 19 '23 at 09:34
  • Lol, the `___PRINT_NUM_COMMON` macro does `jmp %%after_data` before switching to `section .data` and then to `section .text`. Assuming you used it inside `section .text`, that's always just going to be a `jmp next_instruction` no-op, rel8=0. I wonder if they're trying to account for the possibility of being in a section other than `.text`, but [instead of restoring the previous section](https://stackoverflow.com/q/55072277), they're forcibly going to switch to `.text` for the macro and code that follows it! Or if you're putting code into `.data` the you do need to jump over the data... – Peter Cordes Feb 19 '23 at 09:40

0 Answers0