maximum nasm program help

Can anyone help me get this program working?

[code]
;; maximum.asm program determines largest number using nasm
;; source: maximum.asm
;; date: 11/30/2003


section .data
data_items dw 3,67,34,222,45,75,54,34,44,33,22,11,66,0
prompt dw "Max value is: "
lenprompt equ $-prompt

section .text
global _start ;must be declared for linker (ld)


_start: ;tell linker entry point
push ebp ; set up stack frame
mov ebp,esp ; ebp is thumb into stack
push ebx
push esi
push edi

mov edi,0 ;index register
mov eax,[data_items+edi+4] ;base addressing + index+ offset
mov ebx,eax ;first item largest into ebx

start_loop:
cmp eax,0 ;check for last item
je loop_exit ; jump to exit if last item
inc edi ; increment index pointing to next value
mov eax,[data_items+edi+4] ; load next value
cmp ebx,eax ; compare largest value with current item
jle start_loop ; if less than or equal loop to beginning
mov ebx,eax ; else store current item into largest-ebx
jmp start_loop ; jump to start of loop


loop_exit:
push ebx ; save max value
output_prompt:
;; output prompt
mov edx,lenprompt ; count of bytes for write syscall
mov ecx,prompt ; pointer to output buffer
mov ebx,1 ; file discriptor 1 (stdout)
mov eax,4 ; syscall write
int 0x80 ; make call

output_value:
;; output value
mov edx,4 ; count of bytes for write syscall
pop ebx ; get max value
mov ecx,ebx ; pointer to output buffer
mov ebx,1 ; file discriptor 1 (stdout)
mov eax,4 ; syscall write
int 0x80

restore_registers:
pop edi ; restore registers
pop esi
pop ebx
mov esp,ebp
pop ebp

mov eax,1 ; exit() syscall
int 0x80 ;call kernel ebx hold return value maximum
[/code]

Comments

  • Hello,
    Your Nasm command line was not included in the post
    or if you're using an IDE, what IDE & what settings ?
    So I was not able to assemble your code the way you were assembling it.
    I got a simple example code at the end & some code point critiques
    that hopefull will help some what?

    [code]
    data_items dw 3,67,34,222,45,75,54,34,44,33,22,11,66,0
    mov edi,0 ;index register
    mov eax,[data_items+edi+4] ;base addressing + index+ offset
    mov ebx,eax ;first item largest into ebx
    [/code]
    Your data_items are BYTEs but you've declaired them as DW WORDs,
    you're accessing & getting them as Dwords into EAX,
    then INC EDI indexes them as if they were bytes 0-255.
    So your value accessing needs repair.

    Your first access to them skips over the first 4 bytes. EDI+4
    so those first 4 aren't part of the data you're checking.

    eax,[data_items+edi+4] is a complicated way to access the data
    which costs you size & speed,
    MOV ESI,data_items ;ESI = offset address of data, then you can
    LODSB or LODSW or LODSD to get DS:data_item values in AL or AX or EAX
    which also increments ESI 1, 2, or 4 for you automaticlly.

    But if you wanted to fix that part of the code, instead of replace it,
    you might try this untested code. (you debug it)[code]
    data_items DD 3,67,34,222,45,75,54,34,44,33,22,11,66,0 ;DD wastes x4 =bloatware
    MOV EDI,data_items ;offset of values, start at beginning of string
    XOR ECX,ECX ;recieves largest # of string
    JMP SHORT WERK ;git IP over index incrementer
    INCIT: ADD EDI,4 ;aim at the next DWORD
    WERK: MOV EAX,[EDI] ;git a DWORD from [DS:EDI]
    ; MOV EAX,[ES:EDI] ;is an uneeded seg over ride =bloatware
    OR EAX,EAX ;check for 0
    JZ WEDONE
    CMP EAX,ECX
    JBE INCIT ;if EAX is <= ECX jump
    MOV ECX,EAX ;save the largest value in ECX
    JMP SHORT INCIT
    WEDONE:

    ;A better code example might look like this:
    data_items DB 3,67,34,222,45,75,54,34,44,33,22,11,66,0 ;DB = Don't Bloat
    MOV ESI,data_items ;offset of values, start at beginning of string
    XOR ECX,ECX ;recieves largest # of string
    XOR EAX,EAX ;zero extended word & AH for later
    GITONE: LODSB ;git a byte in AL (DD & LODSD might work 4U)
    OR EAX,EAX ;check for 0
    JZ WEDONE
    CMP EAX,ECX
    JBE GITONE ;if EAX is <= ECX jump
    MOV ECX,EAX ;save the largest value in ECX
    JMP SHORT GITONE
    WEDONE:
    [/code]
    So EDI or ESI is all you need for an index offset pointer.
    Nasm discount cheepo poor mans structs are: offset+offset+offset+etc
    and each time you add +offsets that can't be computed by the assembler,
    it has to be computed at run time and that adds size & is slow =bloatware.
    REG+IMMEDIATE can't be computed by the assembler?
    IMMEDIATE+IMMEDIATE can be.
    Immediates don't change in size in a way the assembler can't keep track of it.
    You can reassign a value to a label but the assembler isn't tricked.
    So your MOV EAX,[ES:data_items+EDI+4] was just about as complicated as is
    possible to make it, and MOV EAX,[EDI] works better. DS is the default segment.

    [code]
    data_items dw 3,67,34,222,45,75,54,34,44,33,22,11,66,0
    mov edi,data_items ;index ptr
    mov eax,[edi] ;base addressing
    [/code]
    The code above makes EAX as follows,
    AL = 3 first byte
    AH = 67 2ond byte
    34 = EAX 3rd byte
    222 = EAX hi byte
    so EAX = 0xDE224303 & that's a bunch.
    In Nasm the size of the destination reg sets the size of the value that is
    moved into it. In this case EAX is a DWORD & that's what it gets.
    MOV DESTINATION,SOURCE is how it works.

    The rest of your code goes like this:
    PRINT STRING ok, I take it that this works.

    but then you try to print the value of the largest number in your string
    as if it was a character 0-255. You need a procedure to print your value in
    ASCII text numerical form to std out?
    I have included some simple Nasm .asm .com code that finds the largest value
    in a nul ending string, then prints the value in ASCII text to std out.
    It has a proc you might be able to use: WDECEAX.INC
    It assembled to 131 bytes & uses 8, 16, & 32 bit registers
    [code]
    ;assemble with
    ;NASM -f bin MAXVALUE.asm -o MAXVALUE.com

    BITS 16 ;= default address size, use 16 or 32 bit registers.
    ORG 100h ; PSP header ends & .COM code starts here
    JMP START ; jump over data & procedures

    MSG DB "Max value is: "
    MSGlen EQU $-MSG
    DB 36 ;end of string char = '$'

    VALUES DB 3,67,34,222,45,75,54,34,44,33,22,11,66,0

    ; PROC WDECEAX.INC = Write the DECimal value of EAX to standard out.
    ; Call with, EAX=value to print in ASCII decimal
    ; Returns, no regs
    align 16
    WDECEAX:
    PUSH EAX
    PUSH EBX
    PUSH ECX
    PUSH EDX
    XOR CX,CX ; clear the push count register
    MOV EBX,10
    WDEC1: XOR EDX,EDX ; clear the upper Dword & DX = reg to push
    DIV EBX ; divide EDX:EAX by EBX=10
    ADD DX,48 ; make remainder number a printable ASCII value
    PUSH DX ; least siginificant number (remainder) to stack 1st
    OR EAX,EAX ; check to see if EAX=input_number is divided to 0 yet
    LOOPNE WDEC1 ; get another digit? & this counts the pushes in CX
    MOV AH,2 ; function 2, for interupt 21h, write char in DL
    NEG CX ; two's compliment, reverse CX (holds push count)
    WDEC2: POP DX ; get digit to print, last pushed=most significant
    INT 21h ; print ascii interupt 21h ( function 2 in AH )
    LOOP WDEC2 ; deincrement CX, write another, if CX=0 we done

    MOV DL,13 ; CR carriage return
    INT 21h
    MOV DL,10 ; LF line feed
    INT 21h

    POP EDX ;save/restore regs isn't needed in this program
    POP ECX
    POP EBX
    POP EAX
    RET

    START: MOV AH,9 ;print message to $
    MOV DX,MSG
    INT 21h

    MOV SI,VALUES ;find the largest value
    XOR ECX,ECX ;reciever
    ZZTOP: LODSB
    OR AL,AL ;check for 0=zero
    JZ PRINT ;exit loop if 0=nul ending is found
    CMP AL,CL
    JB ZZTOP
    MOV CL,AL ;if AL > CL, MOV CL=AL
    JMP SHORT ZZTOP ;loops end

    PRINT: MOV EAX,ECX ;print the largest# in ASCII text to std out
    CALL WDECEAX ;print EAX

    MOV AH,8 ;pause
    INT 21h

    MOV AX,4C00h ;exit program
    INT 21h
    [/code]

  • Thanks for the detailed reply. I will have to give your post some thought before I fully comprehend it. lol and I didn't think I was that far off the mark.
  • : Thanks for the detailed reply. I will have to give your post some thought before I fully comprehend it. lol and I didn't think I was that far off the mark.
    [green]
    You wern't far off, a quickie data accessing fix and a printer proc
    was the fix? But I went overboard & covered everything I could think of.
    I hope it helps somehow. Do you want a bunch of free Nasm procedures ?
    http://bitdog.home.att.net/files/nasmenv.zip
    [/green]

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories