1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

how to Branch and Link my program from the "main"

Discussion in 'Assembly Language Programming (ALP) Forum' started by Armnewbie87, Feb 22, 2009.

  1. Armnewbie87

    Armnewbie87 New Member

    Joined:
    Feb 22, 2009
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    I have an assignment where I have to write a code that has 7 subroutines that perform the following:

    · uart_init initializes the user UART for use.
    · output_character transmits a character from the UART to HyperTerminal.
    · read_string reads a string entered in HyperTerminal and stores it as a null-terminated string in memory. The user terminates the string by hitting Enter.
    · output_string transmits a null-terminated string to be displayed in HyperTerminal.
    · read_character reads a character which is received by the UART from HyperTerminal.
    · convert_2_lowercase is the subroutine which converts all the characters in the string to lowercase.
    · sort orders the characters in the word alphabetically.


    So far, I've written this:

    Code:
    AREA Serial, CODE, READONLY 
    EXPORT lab3
    
    SER EQU 0x04 ; Serial Port
    USTAT0 EQU 0x08 ; UART Status Register
    TRANS EQU 0x0C ; Transmit Register
    RECEIV EQU 0x10 ; Receive Register
    BAUD EQU 0x14 ; 
    
    string = "--------------------",0 
    prompt = " Enter a string up to 20 characters long:", 0
    
    ALIGN
    
    lab3
    
    STMFD SP!,{lr} ; Store register lr on stack
    
    BL uart_init ; Branch to uart_init
    
    LDR r10, =prompt ; Prompts user
    BL output_string 
    LDR r8, =string ; Loads string into r8
    
    MOV r9, r8
    BL read_string
    
    
    BL convert_2_lowercase
    
    BL sort
    
    
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    
    uart_init ; INITIALIZE UART 
    
    STMFD SP!,{lr} ; Store register lr on stack
    
    LDR r1, =0x03FFD000 ; Load base address into r1
    MOV r2, #0 ; Turn off serial port
    STR r2, [r1, #SER] ; Contents of 0x3FFD004, stored into r2
    
    LDR r1, =0x03FFD000 ; Load base address into r1
    MOV r2, #3 ; Set port for 8 bits, 1 stop, 0 parity
    STR r2, [r1] ; Store the value 3 into memory address 0x3FFD000
    
    LDR r1, =0x03FFD000 ; Load base address into r1
    MOV r2, #9 ; Turn on serial port
    STR r2, [r1, #SER] ; Store the value 9 into memory address 0x3FFD004
    
    LDR r1, =0x03FFD000 ; Load base address into r1
    MOV r2, #162 ; Set to 9600 baud
    MOV r2, r2, LSL #4 ; Left shift value 162 stored in r2 by 
    ; 4 spots, and recopy into r2
    STR r2, [r1, #BAUD] ; Store left shifted value in r2 into 
    ; memory address 0x3FFD014
    
    LDMFD SP!, {lr} ; Restore register lr from stack 
    MOV pc, lr
    
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    read_string ; READ STRING ENTERED BY USER UNTIL
    ; ENTER KEY IS REACHED
    
    STMFD SP!,{lr} ; Store register lr on stack
    
    STORE BL read_character
    STRB r0, [r9] ; Store the byte
    ADD r9, r9, #1
    BL output_character ; Display the contents of each byte
    CMP r0, #13 ; Finish when the Enter key is pressed
    BNE STORE
    MOV r0, #0
    STRB r0, [r9]
    
    LDMFD SP!, {lr} ; Restore register lr from stack 
    MOV pc, lr
    
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    read_character
    
    STMFD SP!,{lr} ; Store register lr on stack
    
    LOOP LDR r1, =0x03FFD000
    LDR r2, [r1, #USTAT0]
    TST r2, #32
    BEQ LOOP
    LDR r0, [r1, #RECEIV]
    
    LDMFD SP!, {lr} ; Restore register lr from stack 
    MOV pc, lr
    
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    output_character
    
    STMFD SP!,{lr} ; Store register lr on stack
    
    LOOP2 LDR r1, =0x03FFD000 ; Load memory address 0x03FFD000 into r1
    LDR r2, [r1, #USTAT0] ; Load 0x03FFD004 into r2
    TST r2, #64 ; Clear bit 6
    BEQ LOOP2 
    STR r0, [r1, #TRANS] ; Store contents of 0x03FFD004 into r1
    
    LDMFD SP!, {lr} ; Restore register lr from stack 
    MOV pc, lr
    
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    output_string ; SHOW STRING IN HYPERTERMINAL
    ; UNTIL IT REACH END
    
    STMFD SP!,{lr} ; Store register lr on stack
    
    DISPLAY
    LDRB r0, [r10], #1 ; Load the byte from address in r10 into r0
    ; and post-index r10 by 1
    CMP r0, #0 ; Finish when the string comes to a 0
    BEQ DONE2
    BL output_character
    B DISPLAY
    
    DONE2 ; Branch here if null character is reached
    
    LDMFD SP!, {lr} ; Restore register lr from stack 
    MOV pc, lr
    
    
    
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    convert_2_lowercase ; CONVERTS VALUES ENTERED TO THEIR
    ; LOWERCASE FORM
    
    MOV r5, #65 ; r5 holds ascii value for capital A
    MOV r6, #90 ; r6 holds ascii value for capital Z
    
    LDR r11, string ; load address for string into r11
    MOV r3, #0 ; move #0 into r0
    
    LOOPZ MOV r12, r11 ; move value in r11 to r12
    LDRB r3, [r12] ; load byte content from r12 into r0
    
    CMP r3, #13 ; Compare contents of r3 to ascii value for SPACE
    BEQ LOOPE ; If equal to SPACE, Branch to LOOPE and immediately increment
    
    LOOPX CMP r3, r6 ; Compare r0 to Z
    BLE LOOPY ; Branch to LOOPY if r0 < Z
    B DONE ; Otherwise, Branch to DONE
    
    LOOPY CMP r3, r5 ; Compare r0 to A
    BLT DONE ; Branch to DONE if r0 < A
    
    ADD r3, r3, #32 ; Add 32 to acsii value in r3 and copy back to r3
    LOOPE STRB r3, [r12], #1 ; store value in r3 into memory address r12 - Post index by 1
    CMP r12, #0 ; Compare post indexed r12 address to NULL
    BEQ output_string ; Branch to DONE if r12=0
    B LOOPZ ; If unequal, unconditional branch to LOOPZ
    
    DONE ; Done
    
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    
    STMFD SP!,{lr} ; Store register lr on stack
    
    sort
    LDR r7, =string
    MOV r0, #0
    LDRB r0, [r7]
    MOV r8, r7
    
    sort2
    ADD r4, r7, r0
    MOV r1, #0
    ADD r8, r8, #1
    
    after
    LDRB r2, [r4], #-1
    LDRB R3, [r4]
    CMP r2, r3
    BCC skip
    
    STRB r2, [r4], #1
    STRB r3, [r4]
    ADD r1, r1, #1
    SUB r4, r4, #1
    
    skip
    CMP r4, r8
    BHI after
    CMP r1, #0
    BNE sort2
    
    DONE3 
    
    LDMFD SP!, {lr} ; Restore register lr from stack 
    MOV pc, lr
    
    
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    ;-----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    LDMFD SP!, {lr} ; Restore register lr from stack 
    MOV pc, lr
    END
    The code prompts the user fine, and it reads and transmits the string perfectly as well. However, I can't seem to figure out how to Branch and Link my program from the "main" part to my convert_2_lowercase and sort programs so that they function as well.

    I appreciate any and all the help I can get. I'm honestly lost at this point.

    Thank you
     
  2. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    What processor are you using?
     
  3. Armnewbie87

    Armnewbie87 New Member

    Joined:
    Feb 22, 2009
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    ARM Processor
     
  4. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    Hmm.

    > So far, I've written this
    > [225 lines of seemingly perfectly done code, including working BL's]

    Are you sure about that (i.e. that you wrote the code)? I don't really understand the problem description, if you really have written that code. Did your course tutor give you that code and ask you to make the specified changes?

    If you really did write that code would you explain more clearly what it is that you can't figure out? The problem description implies you can't figure out how to make a BL work, but the code you've written shows clearly that you can - sorry if I'm way off track, but people often post stuff their tutor has written and pretend they wrote it, in the hope that we'll do their homework for them.
     
  5. Armnewbie87

    Armnewbie87 New Member

    Joined:
    Feb 22, 2009
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    No no, I wrote that code. My question isn't that I don't know how BL's work, but it's that I can't figure out how to branch and link from the main function, because it's necessary to keep track of the link register so that it returns to the correct location after executing whichever subroutine/label you send it to.

    The BL's that I've used within the program already were easy to understand where they belonged. The link register is loaded and stored correctly so that the linking between the main and the subroutine I send it to isn't lost. The read/transmit aspect of the program was easy for me to grasp, but the attempting to include a sort and convert subroutine within that as well is where I started getting confused. I know that I need to somehow Branch to my output_character after my convert subroutine executes, but if I was to do that, my link register would be changed and thus, mess up the way my program is supposed to execute. I was told by one of my friends that I could just copy and paste my "convert_2_lowercase" subroutine into my read_character subroutine and it should work without using a BL.

    I don't see how to incorporate the sort and convert subroutines into my program.

    The sort subroutine was made using a step-by-step guide online, so that's the only part that I didn't write completely by myself.


    Also, I can assure you that my tutor didn't write any part of that code, nor am I trying to get anyone to complete an assignment for me. This is my first programming class and I'm still trying to get acclimated to this "think like a computer" thing.
     
  6. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    OK, no offence intended.

    > I was told by one of my friends that I could just copy and paste my "convert_2_lowercase" subroutine into my read_character subroutine and it should work without using a BL

    Yep, but that's not what you've done, you've inserted convert_2_lowercase between output_string and sort, and at the top in what I assume to be the "main" function you've got:
    BL read_string
    BL convert_2_lowercase
    BL sort

    So what's the program doing wrong? Does it seem to be calling sort twice?
     
  7. Armnewbie87

    Armnewbie87 New Member

    Joined:
    Feb 22, 2009
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    It doesn't call sort or convert at all, or output the results of either function
     
  8. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    What should it do after returning from sort? At the moment, looking at the code, execution will just run straight into uart_init. Shouuld there be a jump to the last three lines of code?
     
  9. Armnewbie87

    Armnewbie87 New Member

    Joined:
    Feb 22, 2009
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    You mean I should try putting a JMP instruction after my BL sort line in the top, and jump to the end of my program?
     
  10. Armnewbie87

    Armnewbie87 New Member

    Joined:
    Feb 22, 2009
    Messages:
    6
    Likes Received:
    0
    Trophy Points:
    0
    Hmmm, can't edit my first quote. Sorry about the double post.


    After the sort instruction runs, I want both the sort and convert instructions to output to the terminal.

    Would that require me to throw a BL in somewhere after the convert and sort programs that branches to output_char? And if I do that, won't it interfere with the outputing of the original string?
     
  11. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    Well it's not me writing the software so I don't know where it should go. It just looks like it should go somewhere other than into uart_init. Whether it loops back to do more stuff or jumps to the end depends on what you're trying to do.
     
  12. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    Post editing is permitted on this forum when you reach a certain post count, not sure what that is (10 perhaps).

    You should be able to "BL output_string" after "BL sort", the idea of subroutines is that you can call them from anywhere. It looks like output_string outputs the string stored at the address in r10 so you'll need a MOV before you call it.

    You'll also need to consider where the program should go after returning from output_string cos again if you do nothing it'll drop straight into uart_init.
     
  13. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    All your credibility has just been lost and I now know you're lying, *OR* "clshah2" is passing your code off as his own, because his code is identical to yours (there are some minor differences in convert_2_lowercase and sort).

    http://www.go4expert.com/showthread.php?t=16329
     

Share This Page