• Please review our updated Terms and Rules here

Getting started with Macro11 on RT-11 (using simh)

To sort of re-state what some others have said:
Start by spending time learning MACRO in a non-OS environment, then think about doing something under RT later.

Pete
 
If someone needs ChatGPT to learn how to use RT-11, maybe they need to reevaluate their choice of hobbies.
It's a brave new world and the new generation does things differently. I think it's kind of cool that ChatGPT has been trained on RT-11. I'd love to see if it can program Macro-11!
 
I'd love to see if it can program Macro-11!

I tried that out last year by asking it to write a search routine. I had to give it some tutorial assistance, which is summarized below.

Code:
Here’s an updated summary of all the corrections you identified and prompted me to make:

Register Usage:
R6 (stack pointer) and R7 (program counter) are reserved for their special purposes and cannot be used as general-purpose registers. Temporary values were reassigned to other registers or memory locations.

Indirect Addressing Syntax:
Indirect addressing must use the @ symbol (e.g., @TMPIDX) instead of the incorrect (TMPIDX) syntax.

Decimal Literals:
Decimal numbers (e.g., 8, 9, etc.) must be terminated with a period (e.g., 8., 9.) to distinguish them from octal numbers.

Label Length:
Labels must be unique and limited to six characters (e.g., NOTFND instead of NOT_FOUND, NUMEL instead of NUM_ELEMENTS).
Entry Point Specification:

The .END directive must explicitly specify the entry point for the program (e.g., .END START).

Removal of .TEXT and .DATA Directives:
The PDP-11 assembler does not use .TEXT and .DATA directives. The code is placed in the default section for executable instructions, and data is placed in the default section for storage.


With that done, it produced the following code.

Code:
        .TITLE  BinarySearch
        .MCALL  .PRINTS, .EXIT

; Input:
;   R0 - Target value to find
;   R1 - Address of the array
;   R2 - Number of elements in the array

    
START:
        MOV     #TARGT, R0         ; Load the target value into R0
        MOV     #ARRAY, R1         ; Load the base address of the array into R1
        MOV     #NUMEL, R2         ; Load the number of elements into R2

        JSR     PC, BINSEA         ; Call the binary search routine

        ; Check result
        CMP     R5, #-1            ; Was the value not found?
        BEQ     NOTFND             ; If not found, branch
        MOV     #FNDMSG, R0
        .PRINTS                    ; Print "Found!"
        BR      EXIT

NOTFND:
        MOV     #NFMSG, R0
        .PRINTS                    ; Print "Not Found!"
        BR      EXIT

EXIT:
        .EXIT                      ; Exit the program

; Binary Search Routine
; Input:
;   R0 - Target value
;   R1 - Array base address
;   R2 - Number of elements in the array
; Output:
;   R5 - Index of the target value if found, or -1 if not found
BINSEA:
        MOV     #0, R3             ; R3 = low index (initially 0)
        DEC     R2                 ; Adjust R2 to be high index (N - 1)
        MOV     #-1, R5            ; Initialize R5 (result) to -1 (not found)

SEARLO:
        CMP     R3, R2             ; Compare low and high indices
        BGT     SEDONE             ; If low > high, search is done

        MOV     R3, R4             ; Copy low index to R4
        ADD     R2, R4             ; R4 = low + high
        ASR     R4                 ; R4 = (low + high) / 2 (mid index)

        MOV     R4, TMPIDX         ; Use TMPIDX as a temporary index register
        ADD     TMPIDX, TMPIDX     ; Multiply by 2 (word addressing)
        ADD     R1, TMPIDX         ; Compute address of mid element
        MOV     @TMPIDX, TMPVAL    ; Load value at mid element into TMPVAL

        CMP     TMPVAL, R0         ; Compare mid value with target
        BEQ     FOUND              ; If equal, branch to FOUND
        BLT     LTTHAN             ; If mid value < target, branch to LTTHAN

        ; If mid value > target
        MOV     R4, R2             ; High index = mid - 1
        DEC     R2
        BR      SEARLO

LTTHAN:
        MOV     R4, R3             ; Low index = mid + 1
        INC     R3
        BR      SEARLO

FOUND:
        MOV     R4, R5             ; Store mid index in R5 (found)
        BR      SEDONE

SEDONE:
        RTS     PC                 ; Return from subroutine

; Data Section
 
ARRAY:  .WORD   1, 3, 5, 7, 9., 11., 13., 15.  ; Sorted array (all decimal literals terminated)
NUMEL:  .WORD   8.                             ; Number of elements in the array
TARGT:  .WORD   7.                             ; Target value to find

FNDMSG:
        .ASCIZ  "Found!\n"
NFMSG:
        .ASCIZ  "Not Found!\n"
TMPIDX: .WORD   0                              ; Temporary index register
TMPVAL: .WORD   0                              ; Temporary value register
        .END    START                          ; Set the entry point to START

Which executed without crashing, but that's about all.

Code:
.exec sort
Not Found!\n

Still, not bad for a first day of PDP-11 coding...
 
I am surprised by the # characters on the following source lines:

Code:
MOV     #TARGT, R0         ; Load the target value into R0
MOV     #ARRAY, R1         ; Load the base address of the array into R1
MOV     #NUMEL, R2         ; Load the number of elements into R2

This should load the ADDRESS of TARGT into R0, not the value stored at TARGT (etc.).

This will have a knock-on effect through the binary search subroutine of course.

You have correctly used the # in the source line "MOV #0,R3". Of course, this could be replaced by "CLR R3".

Dave
 
Here are semi-related questions. I was looking at a 4000 line RT-11 Macro11 program for an interpreter the other day. It's too long to type in.

1) is there any way to get a program loaded onto some RT-11 system, hardware or emulated, to try it out?
2) if I wanted to port this to RSX/ P/OS, is there anything other than read/write routines that would pose a problem?
 
It's also MACRO-11 source :)
Code:
  .TITLE  BinarySearch

  .MCALL  .PRINT, .EXIT

  .INCLUDE /DSMAC.MAC/
  .INCLUDE /MYMAC.MAC/


; Input:
;   R0 - Target value to find
;   R1 - Address of the array
;   R2 - Number of elements in the array

   
START:

  LET R0 :=  #TARGT         ; Load the target value into R0
  LET R1 :=  #ARRAY         ; Load the base address of the array into R1
  LET R2 :=  #NUMEL         ; Load the number of elements into R2

  CALL BINSEA               ; Call the binary search routine

  ; Check result

  IF R5 NE #-1 THEN         ; Was the value not found?
    .PRINT #FNDMSG          ; Print "Found!"
  ELSE
    .PRINT #NFMSG           ; Print "Not Found!"
  END

  .EXIT                      ; Exit the program

  ; Binary Search Routine
  ; Input:
  ;   R0 - Target value
  ;   R1 - Array base address
  ;   R2 - Number of elements in the array
  ; Output:
  ;   R5 - Index of the target value if found, or -1 if not found

BINSEA:
  LET R3 := #0        ; R3 = low index (initially 0)
  LET R2 := R2 - #1   ; Adjust R2 to be high index (N - 1)
  LET R5 := #-1       ; Initialize R5 (result) to -1 (not found)

  WHILE R3 LE R2 DO   ; Compare low and high indices, if low > high, search is done

    LET R4 := R3 + R2 R.SHIFT 1 ; R4 = (low + high) / 2 (mid index)

    LET TMPIDX := R4 + TMPIDX + R1   ; Use TMPIDX as a temporary index register, Multiply by 2 (word addressing), compute address of mid element
    LET TMPVAL := @TMPIDX            ; Load value at mid element into TMPVAL

    IF TMPVAL EQ R0 THEN             ; Compare mid value with target, if equal, branch to FOUND
      LET R5 := R4
      LEAVE LOOP
    END

    IF RESULT IS GE THEN             ; If mid value > target
      LET R2 := R4 - #1              ; High index = mid - 1
    ELSE
      LET R3 := R4 + #1              ; Low index = mid + 1
    END
  END

  RETURN                             ; Return from subroutine

; Data Section
 
ARRAY:  .WORD   1, 3, 5, 7, 9., 11., 13., 15.  ; Sorted array (all decimal literals terminated)
NUMEL:  .WORD   8.                             ; Number of elements in the array
TARGT:  .WORD   7.                             ; Target value to find

FNDMSG:
        .ASCIZ  "Found!"
NFMSG:
        .ASCIZ  "Not Found!"

    .EVEN

TMPIDX: .WORD   0                              ; Temporary index register
TMPVAL: .WORD   0                              ; Temporary value register

        .END    START                          ; Set the entry point to START

I haven't checked the logic...
 
Here are semi-related questions. I was looking at a 4000 line RT-11 Macro11 program for an interpreter the other day. It's too long to type in.

1) is there any way to get a program loaded onto some RT-11 system, hardware or emulated, to try it out?
Plenty of ways, some were discussed in this thread:

"COPY TT: ", Kermit or a TU58 emulator (TU58FS for example) over a serial port
Papertape or magtape image
Disk image with RT-11 filesystem on it, and a tool like PUTR on the host to manipulate it

I prefer TU58FS -- shared directory mode is especially useful if you're developing on the host.
 
I think - this is correct:
Code:
  LET R0 :=  TARGT         ; Load the target value into R0
  LET R1 :=  #ARRAY         ; Load the base address of the array into R1
  LET R2 :=  NUMEL         ; Load the number of elements into R2
 
I use a HX pseudo device (supported by the VT52 emulator) to transfer information between PC and PDP-11 - it works even over a console terminal
This is quite interesting. What is your PDP-11 system? Emulated or hardware?
 
This should load the ADDRESS of TARGT into R0, not the value stored at TARGT (etc.).
...
You have correctly used the # in the source line "MOV #0,R3". Of course, this could be replaced by "CLR R3".

Dave

There may be a misunderstanding here--all the source code comes from ChatGPT. My initial input was limited to the prompt:

write a pdp-11 binary search routine in assembler

I didn't bother checking the code for anything more than having it assemble without error.
 
Ah, that's why it doesn't work then!

It is syntactically correct, but...

Dave
Right. One of the drawbacks of ChatGPT is that it doesn't really understand anything. It doesn't have semantic connections to help it "know" things. It just has a large language model that allows it memorize from many examples and mimic various languages. But I have seen examples where it can assist with basic programming tasks, especially where they are repetitive.
 
Ah, that's why it doesn't work then!

It is syntactically correct, but...

Dave

Yep, however after I made the two fixes you noted it did report success.

Interestingly, when I pointed out an issue, ChatGPT was fully able to understand its error. For example, when I told ChatGPT that "r6 and r7 can't be used as general purpose registers" it replied as follows:

You're absolutely correct—on the PDP-11, R6 is the stack pointer (SP) and R7 is the program counter (PC), so they cannot be used as general-purpose registers. Let's fix that issue by reassigning the roles of these registers and modifying the code accordingly.

It has the knowledge but is unable to apply it spontaneously.
 
Back
Top