{"id":210,"date":"2011-05-15T12:41:34","date_gmt":"2011-05-15T17:41:34","guid":{"rendered":"http:\/\/snarfblam.com\/words\/?p=210"},"modified":"2013-02-03T22:41:11","modified_gmt":"2013-02-04T03:41:11","slug":"snarfblasm-manual","status":"publish","type":"post","link":"http:\/\/snarfblam.com\/words\/?p=210","title":{"rendered":"snarfblASM Manual"},"content":{"rendered":"<h1>snarfblASM 6502 Assembler<\/h1>\n<p>Updated 12\/2\/2012 for version 1.1 (<a href=\"http:\/\/snarfblam.com\/files\/snarfblasm_new_1.1.zip\">download<\/a>)<\/p>\n<ol>\n<li><a href=\"#commandline\"><!--more-->Command Line<\/a><\/li>\n<li><a href=\"#syntax\">Syntax<\/a><\/li>\n<li><a href=\"#labels\">Labels, Variables, and Expressions<\/a><\/li>\n<li><a href=\"#operators\">Expression Operators<\/a><\/li>\n<li><a href=\"#directives\">Directives<\/a><\/li>\n<li><a href=\"#invalid\">Invalid Opcodes<\/a><\/li>\n<li><a href=\"#unsupported\">Unsupported Features<\/a><\/li>\n<\/ol>\n<p><a title=\"commandline\" name=\"commandline\"><\/a><\/p>\n<h2>Command Line<\/h2>\n<pre>snarfblasm sourceFile [destFile] [switches]\r\n\u00a0\u00a0\u00a0 switches:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 -CHECKING:OFF\/ON\/SIGNED\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Overflow checking in expressions\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 -OFFSET:value\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 value should be a decimal, $hex, or 0xhex offset to patch the dest file\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 -DOT[:OFF\/ON]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Optional dots are enabled for directives (ON)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 -COLON[:OFF\/ON]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Optional colons are enabled for labels (ON)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 -ASM6[:OFF\/ON]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ASM6-like syntax (same as -DOT:ON -COLON:ON)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 -INVALID[:OFF\/ON]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Invalid opcodes are allowed (ON)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 -IPS[:OFF\/ON]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Output IPS format (ON)<\/pre>\n<h2><a title=\"syntax\" name=\"syntax\"><\/a>Syntax<\/h2>\n<p>The snarfblASM syntax is mostly standard 6502 assembler syntax.<\/p>\n<ul>\n<li>Comments start with a semi-colon.<\/li>\n<li>Directives should be preceeded by a dot (unless the <code>-d<\/code> switch is specified).<\/li>\n<li>A label may appear on it&#8217;s own line, or preceeding an instruction or directive. There can be multiple labels on a line.<\/li>\n<li>Hex values should start with $<\/li>\n<li>Binary values should start with %<\/li>\n<\/ul>\n<p>The syntax for the various addressing modes is listed below. Note that for instructions that operate on the accumulator, it is not necessary to specify A as an operand, although it is allowed. snarfblASM treats accumulator addressing as a case of implied addressing.<\/p>\n<pre>    Implied                     CLC\r\n    Accumulator                 ROR\r\n                                ROR A\r\n    Immediate                   LDA #$FF\r\n    Absolute                    LDA $FFFF\r\n    Absolute, X-indexed         LDA $C080, X\r\n    Absolute, Y-indexed         LDA $C080, Y\r\n    Zero-page                   LDA $FF\r\n    Zero-page, X-indexed        LDA $80, X\r\n    Zero-page, Y-indexed        LDA $80, Y\r\n    Indirect                    JMP ($0000)\r\n    Indirect, X-pre-indexed     LDA ($00, X)\r\n    Indirect, Y-post-indexed    LDA ($00), Y<\/pre>\n<p>Square brackets are not supported for indexing. Including an entire expression in parentheses will cause an instruction to be interpreted as indirect addressing. However, to include an entire expression within parentheses for clarity, the unary &#8220;+&#8221; operator (effectively a no-operation) can be used to disambiguate, since it causes the expression to extend beyond the parentheses.<\/p>\n<pre>LDA\u00a0\u00a0 someVar + someOtherVar \/ 2, Y\u00a0\u00a0\u00a0\u00a0 ; Y-indexed\r\nLDA\u00a0 (someVar + someOtherVar \/ 2), Y\u00a0\u00a0\u00a0 ; Indirect, Y-indexed\r\nLDA +(sameVar + someOtherVar \/ 2), Y\u00a0\u00a0\u00a0 ; Y-Indexed<\/pre>\n<p><a title=\"labels\" name=\"labels\"><\/a><\/p>\n<h2>Labels, Variables, And Expressions<\/h2>\n<p>snarfblASM supports the use of assembler variables, or named values. Labels are a special case of assembler variables. Variables can also be explicitly declared.<\/p>\n<pre>someAddress = $A000<\/pre>\n<p>These variables can then be used in expressions (operators are listed below). Variables and expressions can also be used as operands to instructions.<\/p>\n<pre>LDA someAddress + 1\r\nsomeOtherAddress = someAddress + $1000<\/pre>\n<p>A variable can&#8217;t be used within an expression until after it has been declared. Labels are an exception and can be referenced before the label occurs.<\/p>\n<p>snarfblASM works with two kinds of values: 8-bit values (byte) and 16-bit values (referred to as &#8220;word&#8221;, though, technically, the word size for 6502 is 8-bit). The byte versus word distinction can be important in certain circumstances. Adding two 8-bit values produces an 8-bit value, and truncation may occur (or an overflow error if the -o or -os switch is specified). Typically, when an operator is used on a byte and a word, the result is a word.<\/p>\n<pre>var = $FF + $10\u00a0\u00a0\u00a0\u00a0 ; Results in $0F\r\nvar = $FF + $0010\u00a0\u00a0 ; Results in $010F<\/pre>\n<p>snarfblASM decides whether to use absolute addressing or zero-page addressing based on whether the operand is an 8-bit or 16-bit value. To be positive that zero-page addressing is used when an expression or variable is used as an operand, the low-byte (&#8220;&lt;&#8220;) operator can be used. To ensure that absolute addressing is used, the widen (&#8220;&lt;&gt;&#8221;) operator may be used.<\/p>\n<pre>var = $80\r\nlda var\u00a0\u00a0\u00a0\u00a0\u00a0 ; Zero-page\r\nlda &lt;&gt;var\u00a0\u00a0\u00a0 ; Absolute\r\nvar = $0080\r\nlda var\u00a0\u00a0\u00a0\u00a0\u00a0 ; Absolute\r\nlda &lt;var\u00a0\u00a0\u00a0\u00a0 ; Zero-page<\/pre>\n<p>Labels are typically word values. However, if a label is referenced after it occurs, and the label&#8217;s address is less than $100, then the label will be treated as a byte value. This allows pre-declared zero-page labels to be used.<\/p>\n<pre>.enum $0000\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ; Zero-page variables\r\n    Ptr0:\u00a0\u00a0 .dsw\r\n    Ptr2:\u00a0\u00a0 .dsw\r\n.endenum\r\n.base $8000\r\nLDA Ptr0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ; Zero-page addressing<\/pre>\n<p>Two styles of anonymous labels are supported: ASM6-style + and &#8211; labels, and Ophis-style * labels. Though probably a bad plan, mixing them is supported. If both are used, the closest matching anonymous label is used. Named anonymous labels are not currently supported. Anonymous labels always act as word values.<\/p>\n<pre>LDA ++ ; Loads $04\r\n+++ .db $01\r\n*\u00a0\u00a0 .db $02\r\n+\u00a0\u00a0 .db $03\r\n*\u00a0\u00a0 .db $04 ; Closest Match\r\n++\u00a0 .db $05 ; Further Match<\/pre>\n<p><a title=\"operators\" name=\"operators\"><\/a><\/p>\n<h2>Expression Operators<\/h2>\n<p>Listed by precedence:<\/p>\n<pre>++ - (Unary, Post) Increment\r\n-- - (Unary, Post) Decrement\r\n\r\n-\u00a0 - (Unary) Negate\r\n+\u00a0 - (Unary) Effectively a NOP\r\n~\u00a0 - (Unary) Binary Not\r\n!\u00a0 - (Unary) Boolean Not\r\n&lt;\u00a0 - (Unary) Lower Byte\r\n&gt;\u00a0 - (Unary) Upper Byte\r\n&lt;&gt; - (Unary) Widen to word\r\n++ - (Unary, Pre) Increment\r\n-- - (Unary, Pre) Decrement\r\n\r\n&amp;\u00a0 - Binary And\r\n|\u00a0 - Binary Or\r\n^\u00a0 - Binary Xor\r\n\r\n&lt;&lt; - Shift left\r\n&gt;&gt; - Shift right\r\n\r\n*\u00a0 - Multiply\r\n\/\u00a0 - Divide\r\n%\u00a0 - Modulus\r\n\r\n+\u00a0 - Add\r\n-\u00a0 - Subtract\r\n\r\n== - Compare (equal)\r\n!= - Compare (inequal)\r\n&lt;&gt; - Compare (inequal)\r\n&lt;= - Compare (less than or equal)\r\n&gt;= - Compare (greater than or equal)\r\n&lt;\u00a0 - Compare (less than)\r\n&gt;\u00a0 - Compare (greater than)\r\n\r\n&amp;&amp; - Boolean And\r\n|| - Boolean Or\r\n^^ - Boolean Xor<\/pre>\n<p>Boolean and comparison operators result in a byte value of $00 (false) or $FF (true), though any value other than $00 is also considered true. For example, $03 || $00 results in $FF. Shift operators return a byte or word, depending on the left-hand operand. All other binary operators return a value the same width (byte or word) as the widest operand. For example, $7F | $0010 results in (word) $008F.<\/p>\n<p><a title=\"directives\" name=\"directives\"><\/a><\/p>\n<h2>Directives<\/h2>\n<p><code>.alias<\/code><\/p>\n<div style=\"padding-left: 25px;\">\n<p>Behaves identically to normal value declaration. For example, the following have the same effect.<\/p>\n<pre>.alias valueName $FF\r\nvalueName = $FF<\/pre>\n<p>Expressions are supported.<\/p>\n<\/div>\n<p><code>.org<\/code><\/p>\n<div style=\"padding-left: 25px;\">The first .org (or .base) specifies the starting address. Subsequent .org directives will pad to the specified address with zeros. Specifying an address less than the current address is an error.<\/div>\n<p><code>.base<\/code><\/p>\n<div style=\"padding-left: 25px;\">Sets the output address.<\/div>\n<p><code>.db, .byte<\/code><\/p>\n<div style=\"padding-left: 25px;\">Writes a byte value or a list of byte values to the output. An expression may be used for each value.<\/div>\n<p><code>.dw, .word<\/code><\/p>\n<div>Writes a word value or a list of word values to the output. An expression may be used for each value.<\/div>\n<p><code>.data<\/code><\/p>\n<div style=\"padding-left: 25px;\">\n<p>Writes a value or list of values to the output. Values may be bytes or words. For example:<\/p>\n<pre>; Produces the output {10 30 20 05 80}\r\n.org $8000\r\n.data $10, $2030, someLabel\r\nsomeLabel:<\/pre>\n<\/div>\n<p><code>.enum<\/code><\/p>\n<div style=\"padding-left: 25px;\">\n<p>Surpresses output. Useful for declaring variables in RAM. Close a .enum block with .ende or .endenum.<\/p>\n<pre>.enum $0000\u00a0 ; Zero page variables\r\nPtr0:\u00a0\u00a0\u00a0\u00a0 .dw\r\nPtr2:\u00a0\u00a0\u00a0\u00a0 .dw\r\nGameMode: .db\r\n.endenum<\/pre>\n<p>Note that, while you can reference a label before you declare it, in order to use a zero-page instruction with a label, the label must be declared before using it as an operand.<\/p>\n<\/div>\n<p><code>.dsb<\/code><\/p>\n<div style=\"padding-left: 25px;\">\n<p>Inserts storage bytes (useful to reserve addresses for variables within an .enum). By default, one byte with a value of $00 is inserted. A byte count can be specified, optionally followed by a fill value.<\/p>\n<pre>.dsb\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ; emit 1\u00a0 $00\r\n.dsb $10\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ; emit 16 $00\r\n.dsb $20, $FF\u00a0\u00a0 ; emit 32 $FF<\/pre>\n<\/div>\n<p><code>.dsw<\/code><\/p>\n<div style=\"padding-left: 25px;\">\n<p>Inserts storage words (useful to reserve addresses for variables within an .enum). By default, one word with a value of $0000 is inserted. A word count can be specified, optionally followed by a fill value.<\/p>\n<pre>.dsw\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ; emit 1\u00a0 $0000\r\n.dsw $10\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ; emit 16 $0000\r\n.dsw $20, $BEEF ; emit 32 $BEEF\r\n.dsw $40, $48\u00a0\u00a0 ; emit 64 $0048<\/pre>\n<\/div>\n<p><code>.define<\/code><\/p>\n<div style=\"padding-left: 25px;\">\n<p>Defines a symbol. This is to be used for .ifdef statements.<\/p>\n<pre>.define DEBUG<\/pre>\n<\/div>\n<p><code>.if<\/code><\/p>\n<div style=\"padding-left: 25px;\">\n<p>Causes code to assemble only if a specified condition is met. .if directives should NOT refer to or depend on labels that occur later in code. Must be followed by .endif.<\/p>\n<pre>.if $ &gt; $BFFF\r\n.error\u00a0 Too much to fit in bank!\r\n.endif<\/pre>\n<p>An .if block can also contain .elseif and .else clauses.<\/p>\n<\/div>\n<p><code>.ifdef<\/code><\/p>\n<div style=\"padding-left: 25px;\">Causes code to assemble if the specified symbol is defined. Must be followed by .endif.<\/div>\n<p><code>.ifndef<\/code><\/p>\n<div style=\"padding-left: 25px;\">Causes code to assemble if the specified symbol is not defined. Must be followed by .endif.<\/div>\n<p><code>.include<\/code><\/p>\n<div style=\"padding-left: 25px;\">Includes a separate ASM file.<\/div>\n<p><code>.incbin<\/code><\/p>\n<div style=\"padding-left: 25px;\">Inserts a binary file in the output.<\/div>\n<p><code>.error<\/code><\/p>\n<div style=\"padding-left: 25px;\">\n<p>Produces an error. Useful with directives such as .if to identify problematic conditions.<\/p>\n<pre>beforeIncBin:\r\n.incbin \"somefile\"\r\nafterIncBin:\r\nincludedFileSize = afterIncBin - beforeIncBin\r\n\r\n.if includedFileSize &gt; $1000\r\n.error\u00a0 \"somefile\" too large ; Assembler will fail with specified error message\r\n.endif<\/pre>\n<\/div>\n<p><code>.overflow<\/code><\/p>\n<div style=\"padding-left: 25px;\">\n<p>Specify an option, &#8220;ON&#8221; or &#8220;OFF&#8221;. This option is &#8220;OFF&#8221; by default. If .overflow is enabled, any expressions that produce an overflow will result in an assembler error. For example:<\/p>\n<pre>value_A = $80 * $2 ; Results in 0\r\n.overflow ON\r\nvalue_B = $80 * $2 ; Produces an error<\/pre>\n<\/div>\n<p><code>.signed<\/code><\/p>\n<div style=\"padding-left: 25px;\">\n<p>Specify an option, &#8220;ON&#8221; or &#8220;OFF&#8221;. This option is &#8220;OFF&#8221; by default. This option is used in conjunction with .overflow. If .signed is enabled, overflow detection will operate in signed mode, giving a range of -128 to 127 for bytes, and -32768 to 32767 for words. For example:<\/p>\n<pre>.overflow ON\r\nvalue_A = $FF ;\r\nvalue_B = $10 ;\r\n.signed ON\r\nvalue_C = value_A + value_B\u00a0 ; (-1 + 16 = 15, or $F)\r\n.signed OFF\r\nvalue_D = value_A + value_B\u00a0 ; ERROR! (255 + 16 = 271, or $10F)<\/pre>\n<\/div>\n<p><a title=\"invalid\" name=\"invalid\"><\/a><\/p>\n<h2>Invalid Opcodes<\/h2>\n<p>Invalid opcodes, those that are not part of the proper 6502 specification, can be used if the -i command line switch is used. This allows for unsupported instructions. For example, <code>LAX #$55<\/code> (load A and X with #$55) would normally result in an error, but if the <code>-i<\/code> switch is used, the code will assemble.<br \/>\n<a title=\"unsupported\" name=\"unsupported\"><\/a><\/p>\n<h2>Unsupported Features<\/h2>\n<ul>\n<li>Macros<\/li>\n<li>Tables\/non-ASCII string literals<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>snarfblASM 6502 Assembler Updated 12\/2\/2012 for version 1.1 (download)<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[31,3,1],"tags":[26,27,28],"class_list":["post-210","post","type-post","status-publish","format-standard","hentry","category-asm-romhacking","category-romhacking","category-uncategorized","tag-26","tag-asm","tag-snarfblasm"],"_links":{"self":[{"href":"http:\/\/snarfblam.com\/words\/index.php?rest_route=\/wp\/v2\/posts\/210","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/snarfblam.com\/words\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/snarfblam.com\/words\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/snarfblam.com\/words\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/snarfblam.com\/words\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=210"}],"version-history":[{"count":28,"href":"http:\/\/snarfblam.com\/words\/index.php?rest_route=\/wp\/v2\/posts\/210\/revisions"}],"predecessor-version":[{"id":423,"href":"http:\/\/snarfblam.com\/words\/index.php?rest_route=\/wp\/v2\/posts\/210\/revisions\/423"}],"wp:attachment":[{"href":"http:\/\/snarfblam.com\/words\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=210"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/snarfblam.com\/words\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=210"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/snarfblam.com\/words\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=210"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}