4

First off: sorry if this is a dupe! I have searched a bit and have not found a resource which satisfactorily explains this.

n00bish question here!

I am trying to understand what the .byte directive does. Different sources say different things, the gist of which is something like :

.db, DB, .byte, etc. lay down the exact bytes you specify, as data and not as instructions (http://forum.6502.org/viewtopic.php?f=2&t=2374)

The cc65 manual gives a similarly vague:

.byte: Define byte sized data. Must be followed by a sequence of (byte ranged) expressions or strings.

Example:

        .byte   "Hello "
        .byt    "world", $0D, $00

(http://www.cc65.org/doc/ca65-11.html)

I don't know what that means. I thought that all operations related to defining data were variations on reading and writing memory addresses. So something like this (from a tut on NES development)

; Number of PRG-ROM blocks
.byte $01
; Number of CHR-ROM blocks
.byte $01
; ROM control bytes: Horizontal mirroring, no SRAM
; or trainer, Mapper #0
.byte $00, $00

What is it doing exactly? Can it all be explained in terms of opcodes, or is it doing something fancier? To me, it looks like it is maybe writing sequential data, starting from the zero page, something like this??:

LDA #$01
STA $00
LDA #$01
STA $01
LDA #$00
STA $02
LDA #$00
STA $03

Am I way off here? I have been reading 6502 Software Design by Leo Scanlon and I have seen no reference to that ( or any ) directive. I am learning 6502 for the purpose of NES development and all example code is riddled with .byte , .ascii , and several other directives. I really wanted to try and get a solid foundation in 6502 from an academic text like the Scanlon book before trying to navigate the world of user-contributed NES tutorials, but this is becoming a road block to my understanding of NES 6502.

chiliNUT
  • 18,989
  • 14
  • 66
  • 106
  • 3
    The directives put bytes directly in the output. There is no memory access. For example, `LDA #1` is the same as `.byte $A9, $01`. – Raymond Chen Mar 02 '15 at 05:28
  • what is "the output"? – chiliNUT Mar 02 '15 at 05:34
  • becuase $A9 is the opcode for LDA in absolute addressing mode... – chiliNUT Mar 02 '15 at 05:34
  • so why would a piece of code do something like `.byte $01,$01,$01,$01,...` to define a list of values, such as the exmaple here: http://forum.6502.org/viewtopic.php?f=2&t=2374 where it is being used to apparantly define a list of 32 values and load them into memory? – chiliNUT Mar 02 '15 at 05:35
  • @RaymondChen given that your example could translate into a LDA statement, are all .byte statements translatable into a set of opcode instructions? – chiliNUT Mar 02 '15 at 05:43
  • 2
    It's the other way around. All opcodes are translatable into `.byte` directives. That's what an assembler does. it takes opcodes and converts them into bytes. – Raymond Chen Mar 02 '15 at 05:51
  • @RaymondChen OK, that makes sense, but I'm still confused. What is the reason to "lay out bytes" as opposed to using opcodes? why do something like `.byte $01` `.byte $01` `.byte $01 $1A` instead of using opcodes? What is being accomplished? – chiliNUT Mar 02 '15 at 05:56
  • 1
    Like it says in the article you quoted: "as data and not as instructions." If you need to put data in your program, you just want to put the bytes in the memory image. – Raymond Chen Mar 02 '15 at 06:38
  • what is the "memory image"? – chiliNUT Mar 02 '15 at 06:42
  • The output of the assembler. The program that is going to be loaded into memory. – Raymond Chen Mar 02 '15 at 06:48
  • 1
    haha this was a bit drawn out...the "output" is the content of the program file. This all makes sense now. @RaymondChen thank you for your help in understanding this – chiliNUT Mar 02 '15 at 16:56
  • Not sure what you thought the point of an assembler was if not to generate a program as output. – Raymond Chen Mar 02 '15 at 19:10
  • @RaymondChen it was just a context thing, I took "the output" to mean, "the output of the function", as in the return value or end result of invoking the directive, I think if you had said "the binary" or "the final program" I would have caught on quicker. – chiliNUT Mar 02 '15 at 19:16

2 Answers2

3

There is two different things to consider here. You are mixing the ROM memory location, where the values are always here (they can't, and shouldn't, be "loaded in"), and RAM, where the contents are undefined when the system is powered on, and where any data you'd want to use have to be effectively "loaded in" at some point.

For example :

.byte $00, $01, $02, $03

Will add somewhere in the ROM those 4 bytes. They are not "loaded in", they are always here.

As opposed to :

ldx #$00
stx somewhere
inx
stx somewhere+1
inx
stx somewhere+2
inx
stx somewhere+3

If somewhere points to RAM, then this will load the bytes $00, $01, $02, $03 in this location. Those bytes are only here in the RAM location after you load those values, and until you overwrite the RAM with other values.

Now, as for your example, this is actually a confusing one, because it defines bytes of the iNES header format, which is always 16 bytes long. Those bytes are NOT part of neither the ROM or the RAM, but are just a header convention for storing NES ROMs on PCs.

The example you saw just tricks the assembler into thinking the header is part of the ROM when in fact it is not. It is just one of the ways to do it. Another way would be to generate a clean "raw" ROM image with the assembler and add the iNES header separately when building, this is how I do it personally.

I hope this helped.

Bregalad
  • 634
  • 7
  • 15
  • so, its like you are literally writing those bytes to the file. that is the "output" that @Martin was speaking of. And also explains the point of .ascii "NES" because the intent is literally to have the phrase "NES" present in the header of the file. That clears this up, thank you! – chiliNUT Mar 02 '15 at 16:51
  • Yeah, in this case the "output" would be directly a iNES file including the iNES header, the PRG-ROM, and possibly the CHR-ROM if one is present. However, in other cases the output could be something else, for instance if you program for a PC in assembly you can also use .byte to place constant data in the program section. Using .byte to generate the iNES header is just a dirty trick. – Bregalad Mar 02 '15 at 16:55
  • I'm not familiar enough with asm to see why that is "dirty". What would be the "clean" way of setting the iNes header? – chiliNUT Mar 02 '15 at 16:58
  • 1
    Well, personally I make the header in a separate file and use the (windows) command line `copy /b header.bin + prgrom.bin + chrrom.bin game.nes` in order to create a iNES ROM. This does not mean it's the only option (nor the best one). – Bregalad Mar 02 '15 at 17:02
  • oh ok. so each of the files is assembled individually, and then you manually concatenate them, which achieves a similar result to setting `bytes` for the header, and using `incbin` for the other files (the tut I was looking at uses `.incbin`) – chiliNUT Mar 02 '15 at 17:08
  • 1
    Yeah, ,incbin works exactly like .byte, except it automatically pastes a whole binary file in your ROM. Good luck :) – Bregalad Mar 02 '15 at 17:09
1

After reading the comments I try to give an answer:

In the memory of most computers all kind of data (including code) is stored in form of bytes.

This means that an assembler has to translate all instructions to bytes in the end.

The instruction "LDA $1234" would be stored as three bytes: $AD, $12 and $34.

Using the instructions ".byte", ".word" and ".long" (may be 6502 does not support ".long") you can directly instruct the assembler to put some given bytes to some memory location instead of the byte that represents some instruction.

Imagine the following piece of code which is part of the operating system:

LDX $2000
STA 0,X
...
JSR $2001

In this case the byte at address $2000 will contain an address in the zero page where the A register will be written to while the byte at address $2001 is the first byte of the actual code.

The assembler code for data starting at addresses $2000 may now look like this:

# Zero-page address where the OS will store the A register
.byte $12
# Actual code called by the OS
LDA $12
...
RTS

I hope this helps.

--- Edit ---

About your example with the '.ascii "iNES"' line:

These lines are only present in a program for a NES emulator, not in a program for a real NES device.

When using a very, very broad definition of the term "operating system" you might say that the NES emulator is some kind of "operating system". In this case the reason for the ".byte" lines in your example is the same one as described above:

The "operating system" (= NES emulator) will read the first 16 bytes of the file, check these bytes, do something with these bytes and then actually runs the code.

You may also have seen the following lines in the code:

.advance $FFFA
.word vblank, reset, irq

These two lines are also not 6502 assembler instructions but they are directives to the assembler:

They instruct the assembler to write six special bytes to address $FFFA. This is necessary because a 6502 CPU requires six bytes representing three special addresses at the addresses $FFFA-$FFFF.

Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
  • I am still confused by the example here: http://forum.6502.org/viewtopic.php?f=2&t=2374 where `.bytes` seems to be used to load a list of values into memory – chiliNUT Mar 02 '15 at 06:29
  • a better example is this: `; iNES identifier .ascii "NES" .byte $1a ; Number of PRG-ROM blocks .byte $01 ; Number of CHR-ROM blocks .byte $01 ; ROM control bytes: Horizontal mirroring, no SRAM ; or trainer, Mapper #0 .byte $00, $00 ; Filler .byte $00,$00,$00,$00,$00,$00,$00,$00 ; PRG-ROM .include "tutorprg.p65" ; CHR-ROM .include "tutorchr.p65"` what on earth is "filler" doing? (http://hackipedia.org/Platform/Nintendo/NES/tutorial,%20NES%20programming%20101/NES101.html) – chiliNUT Mar 02 '15 at 06:35
  • Um, it is filler. Bytes that don't do anything. – Raymond Chen Mar 02 '15 at 06:50
  • 1
    No, the iNES is not required by any operating system, and the first instruction is not after the iNES header at all. There is no OS in the NES, by the way. Sorry but your comment is just nonsense. You seem to be confusing with the C64 or any other machine. – Bregalad Mar 02 '15 at 16:51