ASM

Strictly for discussing ZSNES development and for submitting code. You can also join us on IRC at irc.libera.chat in #zsnes.
Please, no requests here.

Moderator: ZSNES Mods

Post Reply
Noxious Ninja
Dark Wind
Posts: 1271
Joined: Thu Jul 29, 2004 8:58 pm
Location: Texas
Contact:

ASM

Post by Noxious Ninja »

Where to start? I've got a bunch of x86 assembler docs here, so I'm OK in the regard. I like jumping in and thrashing around until I've got it. Anyway... I don't get it yet. :P

Let's take this nice block of code from guiwindp.inc:

Code: Select all

GUIStringGreater:
    ; compares string at esi to edi and returns 1 to al if esi is >, else 0
    push esi
    cmp word[esi],'.'
    je .less
    cmp word[esi+32],'.'
    je .greater
    cmp word[esi],'..'
    je .less
    cmp word[esi+32],'..'
    je .greater
.nextchar
    cmp byte[esi],0
    je .less
    cmp byte[esi+32],0
    je .greater
    mov al,[esi]
    mov cl,[esi+32]
    cmp al,'a'
    jb .noucase1
    cmp al,'z'
    ja .noucase1
    sub al,'z'-'Z'
.noucase1
    cmp cl,'a'
    jb .noucase2
    cmp cl,'z'
    ja .noucase2
    sub cl,'z'-'Z'
.noucase2
    cmp al,cl
    jb .less
    ja .greater
    inc esi
    jmp .nextchar
.less
    mov al,0
    jmp .skip
.greater
    mov al,1
.skip
    pop esi
    ret
OK...

Let's see how much I understand.

push esi -- copies ESI to the stack, right?

cmp word[esi],'.' -- [] is the NASM equivalent to C's * pointer operator, right?

je .less -- combined with the above instruction, if the first two bytes of the string pointed to by esi are 002E, we jump to less.

I don't understand that. I don't even see where EDI comes into the picture at all. :P If someone could explain a few things I might actually understand this. :D
[u][url=http://bash.org/?577451]#577451[/url][/u]
Overload
Hazed
Posts: 70
Joined: Sat Sep 18, 2004 12:47 am
Location: Australia
Contact:

Post by Overload »

Just a quick glance. It looks like the code is comparing two strings one at [esi] and the other at [esi+32]. It also seems to be changing the character case, so comparison is case insensative.

Best guess. It is used to compare filenames?
grinvader
ZSNES Shake Shake Prinny
Posts: 5632
Joined: Wed Jul 28, 2004 4:15 pm
Location: PAL50, dood !

Post by grinvader »

My shot at it. It's quite easy once you get some key values in your 'brain cache'. :wink:

I'll comment along the code...

Code: Select all

GUIStringGreater:               ; function label, not globally declared

push esi                        ; saves esi on top of stack.

    cmp word[esi],'.'           ; compares the 2 bytes (little endian) at memory location pointed to by esi
    je .less                    ; current value with 0x002E ({ '.', 0 } string) as you should know, the first
                                ; element in a directory is always '.', and the second is always '..' So if the
                                ; 'esi' string is '.', that means it is "smaller" since nothing goes before that.
                                ; of course, the hard part was maybe to realise this function could be used with
                                ; directory listings

    cmp word[esi+32],'.'        ; now it makes sense, if the second string (located 32 bytes ahead of the first) is
    je .greater                 ; the first element, AND the first string isn't this very element, then first
                                ; string is "greater".

    cmp word[esi],'..'          ; now checking second special case for first string...
    je .less

    cmp word[esi+32],'..'       ; and for second string.
    je .greater

; now we've tested for the special cases, we're gonna have to make some kind of loop to sort all possible filenames
; we may encounter and tell which is 'greater'

.nextchar                       ; typical loop label name
    cmp byte[esi],0             ; check for end of string. the shortest string is always the 'smallest'
    je .less

    cmp byte[esi+32],0          ; if the second string is shorter, the first is "greater"
    je .greater

    mov al,[esi]                ; puts charA, currently pointed by esi value, in al register
    mov cl,[esi+32]             ; puts charB, currently pointed by esi value + 32, in cl register
                                ; this will make comparisons easy

    cmp al,'a'                  ; if charA is under 'a', it's not lowercase
    jb .noucase1

    cmp al,'z'                  ; again, not lowercase
    ja .noucase1

    sub al,'z'-'Z'              ; transforms lowercase charA into uppercase - another possible line: "sub al,20h"
                                ; (or 32, if you like decimal)

.noucase1                       ; if charA wasn't lowercase, we got here from a jump
    cmp cl,'a'
    jb .noucase2
    cmp cl,'z'
    ja .noucase2
    sub cl,'z'-'Z'

.noucase2                       ; same stuff with charB, obviously we're gonna work with uppercases

    cmp al,cl                   ; the comparison.
    jb .less                    ; 1st string smaller...
    ja .greater                 ; or greater...
    inc esi                     ; if equal, look at next char in both strings...
    jmp .nextchar               ; and loop !

.less                           ; if we got here, it means first string is 'smaller'
    mov al,0
    jmp .skip

.greater                        ; first string is 'greater'
    mov al,1

.skip
    pop esi                     ; restore initial pointer position, at beginning of first string
    ret                         ; AKA 'GTFO'
Overload got it. Directory/filename comparison.
Probably to sort them correctly in load menu box.
Noxious Ninja wrote:

Code: Select all

    ; compares string at esi to edi and returns 1 to al if esi is >, else 0
I don't even see where EDI comes into the picture at all.
Well, it's probably an old comment from an older version, where these lines were present in the beginning:

Code: Select all

    mov edi,esi
    add edi,32
Then, every time esi+32 is used edi was used.

Setting edi outside the function then comparing [esi] with [edi] could give a more powerful function, since it could compare anything with anything. (this one only compares [esi] with [esi+32])
Last edited by grinvader on Sun May 22, 2005 10:52 pm, edited 1 time in total.
皆黙って俺について来い!!

Code: Select all

<jmr> bsnes has the most accurate wiki page but it takes forever to load (or something)
Pantheon: Gideon Zhi | CaitSith2 | Nach | kode54
kieran_
Mugwump
Posts: 824
Joined: Fri Jul 30, 2004 9:05 pm

Post by kieran_ »

grinvader wrote:Big lump of code
That is pretty cool...
bztunk
Hazed
Posts: 84
Joined: Mon Dec 27, 2004 9:08 pm
Location: In A.D. 2101, war was beginning.

Post by bztunk »

kieran wrote: That is pretty cool...
A+ post, will read again.
laserbeak43
Rookie
Posts: 21
Joined: Thu Aug 04, 2005 3:11 am
Contact:

Post by laserbeak43 »

where did you guys learn your assembly?
could you point me to the right docs?
i have the snes starter kit and a whole bunch of snes docs but no assembly stuff
grinvader
ZSNES Shake Shake Prinny
Posts: 5632
Joined: Wed Jul 28, 2004 4:15 pm
Location: PAL50, dood !

Post by grinvader »

Assembly is per-cpu. You have to mention which kind of assembly you wish to learn.

For example, I learnt 80386 ASM from this (actually own a hard copy), especially chapter 17 (instruction set) and from all the stuff Nach and TRAC told me (especially about pointers and type sizes).

But x86 ASM cannot be run on anything else than x86 cpus (or x86 emulators). You have to consider this lack of portability before starting a project in asm.
皆黙って俺について来い!!

Code: Select all

<jmr> bsnes has the most accurate wiki page but it takes forever to load (or something)
Pantheon: Gideon Zhi | CaitSith2 | Nach | kode54
laserbeak43
Rookie
Posts: 21
Joined: Thu Aug 04, 2005 3:11 am
Contact:

Post by laserbeak43 »

grinvader wrote:Assembly is per-cpu. You have to mention which kind of assembly you wish to learn.

For example, I learnt 80386 ASM from this (actually own a hard copy), especially chapter 17 (instruction set) and from all the stuff Nach and TRAC told me (especially about pointers and type sizes).

But x86 ASM cannot be run on anything else than x86 cpus (or x86 emulators). You have to consider this lack of portability before starting a project in asm.
yeah i know that but i didnt think i had to be so specific. forgive me. interesting i didnt know that the x86 was so "esoteric".

i'm interested inthe spc700 for now for music. and the segaa ym chips. also the z80.
i would probably learn alot from the ID too hah? since it's so famous.

i thonk neviksti might give me a few pointers this weekend and send me on my way :D
badinsults
"Your thread will be crushed."
Posts: 1236
Joined: Wed Jul 28, 2004 1:49 am
Location: Not in Winnipeg
Contact:

Post by badinsults »

This site has a snes assembler tutorial.
<pagefault> i'd break up with my wife if she said FF8 was awesome
laserbeak43
Rookie
Posts: 21
Joined: Thu Aug 04, 2005 3:11 am
Contact:

Post by laserbeak43 »

GOATSnEs wrote:This site has a snes assembler tutorial.
arf?? i'll search for it
Post Reply