If you have some basic background in programming, or even if you don’t, but want to get some then you can turn to chatbots and in particular to Windows Copilot (I’ll refer to it as Copilot for shortness). You can use Gemini, ChatGPT, Claude etc. if you prefer, and they’ll be as useful. This is what I did just recently when I stumbled upon a post by Dave Plummer at X, where he talked about the need for programmers to understand how compilers produced their output, hence the need to know assembly language. By the way, Dave Plummer developed Windows Task Manager when he was a programmer with Microsoft . He has a YouTube channel where he posts interesting videos related to programming.
Why chatbots can be helpful in this case? First, if you didn’t program in assembly before it can be difficult to approach it. Second, chatbots are very helpful in explaining existing code in any programming language they had in their training data. And, I guess, it means it should know details about most modern programing languages.
Well, next I’ll provide a screenshot of that post, then I’ll show you that chatbot can transcribe the code from an image alone and explain what we are looking at there. The short summary is that post was about binary to ASCII (BTOA) conversion program written in PDP-11 computer assembly. By the way, all these details where extracted by Copilot from the code in the image. Then, I’ve used Copilot to explain to me in detail how the code works to get full understanding of it.
Pay attention, that I use line separator to mark when the response from chatbot has finished.
Original post
I suppose there's a whole class of programmers for whom a compiler is akin to magic, but knowing what's getting emitted and how it works is fundamental to your success over the long haul.
I suppose there’s a whole class of programmers for whom a compiler is akin to magic, but knowing what’s getting emitted and how it works is fundamental to your success over the long haul. Write some assembly. Read the Dragon book on an airplane. AI will still be here when you get back. In five years, anyone capable of structured thought will be able to become a prompt engineer, but only 1% of software developers will actually be able to debug the stuff that comes out the other end. Be the 1%
What did I do next?
As I’ve mentioned I’ve copy and pasted the image in Copilot and asked it to transcribe the code from the image and explain what it’s doing.
Prompt: Transcribe the code from the image and explain (an image was attached as can be seen in the screenshot below). Response:
Below comes a full response.
Here’s the full transcription of the PDP-11 assembly code using MACRO-11 syntax, followed by a detailed explanation: Transcribed Code
.TITLE BTOA ; Program title
.MCALL .PRINT,.EXIT,.TTYOUT ; System macros
HELLOMSG: .ASCIZ /BTOA Example/
.EVEN ; Ensure we're on a word boundary
START: .PRINT #HELLOMSG
MOV #12345., R0 ; Number to convert
JSR PC, BTOA
.EXIT
BTOA:
MOV R0, -(SP) ; Save R0 on stack
MOV R1, -(SP) ; Save R1 on stack
MOV R2, -(SP) ; Save R2 on stack
MOV R0, R1 ; Move number to R1 (low part of dividend)
CLR R0 ; Clear R0 (high part of dividend)
DIV #10., R0 ; Divide R0:R1 by 10, quotient in R0, remainder in R1
TST R0 ; Check if quotient is 0
BEQ PRINT ; If quotient is 0, print digit
JSR PC, BTOA ; Recursive call with quotient
PRINT: ADD #'0, R1 ; Convert remainder to ASCII
MOV R1, R0 ; Move ASCII digit to R0
.TTYOUT R0 ; Print the digit
MOV (SP)+, R2 ; Restore R2
MOV (SP)+, R1 ; Restore R1
MOV (SP)+, R0 ; Restore R0
RTS PC ; Return
.END START
🧠 Explanation
This program converts a binary number (in this case, 12345) to its ASCII decimal representation and prints it to the terminal.
🔹 Header and Setup
.TITLE BTOA: Sets the title of the program.
.MCALL .PRINT,.EXIT,.TTYOUT: Declares macros for printing, exiting, and terminal output.
HELLOMSG: .ASCIZ /BTOA Example/: Defines a null-terminated string.
.EVEN: Ensures the next instruction is aligned on a word boundary.
🔹 Main Routine (START)
.PRINT #HELLOMSG: Prints the greeting message.
MOV #12345., R0: Loads the number 12345 into register R0.
JSR PC, BTOA: Calls the BTOA subroutine to convert and print the number.
.EXIT: Ends the program.
🔹 Subroutine (BTOA)
Saves registers R0, R1, and R2 to the stack.
Sets up for division: moves the number to R1, clears R0 to form a 32-bit dividend.
DIV #10., R0: Divides R0:R1 by 10. Quotient goes to R0, remainder to R1.
TST R0: Tests if quotient is zero.
If yes, go to PRINT.
If not, recursively call BTOA with the quotient.
PRINT: Converts the remainder (digit) to ASCII by adding '0', then outputs it using .TTYOUT.
Restores registers from the stack and returns.
This recursive approach ensures digits are printed in the correct order (most significant to least significant). Would you like to see how this would look in C or another language for comparison?
Let’s try to understand how it works in more detail.
Question: First of all, what is BTOA?
Response:
Great question! 🧠
BTOA stands for Binary To ASCII. It’s a common abbreviation used in programming to describe the process of converting a binary (or numeric) value into its ASCII character representation, typically for display or output purposes.
🔍 What does “Binary to ASCII” mean?
Binary: In this context, it refers to a numeric value stored in binary format (e.g., the number 12345 in machine-readable form).
ASCII: The American Standard Code for Information Interchange — a character encoding standard that maps numbers to printable characters like '0' to '9', 'A' to 'Z', etc.
Okay, now that we know what that mysterious BTOA was how about we understand what happens inside this block of code that resides inside the BTOA function?
MOV R0, R1 ; Move number to R1 (low part of dividend)
CLR R0 ; Clear R0 (high part of dividend)
DIV #10., R0 ; Divide R0:R1 by 10, quotient in R0, remainder in R1
TST R0 ; Check if quotient is 0
BEQ PRINT ; If quotient is 0, print digit
JSR PC, BTOA ; Recursive call with quotient
Also, before jumping to Copilot for help we can see assembly language program that is doing some computation using registers in CPU such as R0 and R1. We can see the data is moved, cleared, a division is done and then there is a conditional logic on lines 5, 6 and 7. In the screenshot it corresponds to lines 22, 23 and 24.
So what is the explanation ? Response:
This block of PDP-11 assembly code is the core of the binary-to-ASCII conversion logic. It performs division by 10 to extract digits from a number and uses recursion to print them in the correct order. Here’s a breakdown of each line:
🔍 Line-by-Line Explanation
18 MOV R0, R1 ; Move number to R1 (low part of dividend)
Copies the number from R0 to R1.
This sets up the 32-bit dividend for division: R0:R1 (high:low).
19 CLR R0 ; Clear R0 (high part of dividend)
Clears R0 to zero.
Now the full dividend is 0:R1, effectively treating the original number as a 32-bit value with high word = 0.
20 DIV #10., R0 ; Divide R0:R1 by 10, quotient in R0, remainder in R1
Performs a 32-bit division of R0:R1 by 10.
After this:
R0 contains the quotient (i.e., number / 10)
R1 contains the remainder (i.e., number % 10), which is the rightmost digit
22 TST R0 ; Check if quotient is 0
Tests if the quotient is zero.
This determines whether there are more digits to process.
23 BEQ PRINT ; If quotient is 0, print digit
If R0 is zero, it means this is the last digit.
Branches to PRINT to output the digit.
24 JSR PC, BTOA ; Recursive call with quotient
If R0 is not zero, it means there are more digits.
Recursively calls BTOA with the quotient in R0, continuing the process.
🧠 Summary
This block:
Extracts the least significant digit of the number.
Uses division and recursion to process digits from most significant to least significant.
Ensures digits are printed in the correct order by printing only after recursion unwinds.
Conclusion
Well, I guess it clarifies a bit what the code is doing. And you probably got a point of how you can use a chatbot to help you understand a piece of code in a programming language you probably never saw and drill down to nitty gritty details of the implementation and really understand how it works.
Canada Post AddressComplete API allows a user to search for an address within Canada and other countries. Within Canada results can be in both English and French languages. There are two ways to invoke Canada Post API:
To embed css and JavaScript flies that can be copy and pasted from the Canada Post website
To directly call Canada Post API
API setup prerequisites
To be able to call Canada Post AddressComplete API there is a need to setup an account with Canada Post which will provide you with an API Key and also allow you to configure particular URLs to be able to issue search requests using that API Key.
This API Key is for all intents and purposes public, since it can be easily discovered by looking at the API calls in the Network tab in a browser’s developer tools. What prevents this API Key from being used by 3rd parties is assigning it to particular URLs that it can be called from and adding rate limiting and other options as discussed here.
Embedded css and JavaScript files
One way to integrate with Canada Post API is to add the following three tags in the head tag of the index.html page of the project.
Where the css link provides the styling for the Canada Post API script added in the script tag and the second script provides the mapping from the form fields in which you want to use Address Search to the existing fields in the Canada Post API script. More details about how the mapping is done can be found here.
Direct call to Canada Post API
It is also possible to integrate directly with the Canada Post API using their official documentation by using two Find and Retrieve endpoints they expose. More details about each endpoint will be provide below.
Address Lookup Flow
There can be a number of possible scenarios while using Canada Post AddressCompleet API to search for an address. For example, issuing a Find request will return a list of addresses that are similar to the search term used by a user.
Also, what is important each address in that list contains a Next field which can have one of two options: Find or Retrieve. This field is important when one of the search results is a street that has a number of houses or an apartment building with a number of apartments. In this case such an address will have Next field with Find value.
Possible search flow scenarios
Scenario
First endpoint call
Next Action (call)
Result
Notes
1
Look up of a single existing address
Find
Retrieve
Detailed address returned by the Retrieve request
2
Look up of a street or an apartment building address
Find
Find with LastId value from the first call
List of houses/apartments
In this case there is a need to issue additional Retrieve request to get a detailed address.
3
Look up of a specific address by ID from Find request result
Find request endpoint is described in this official page. Its purpose is to look up addresses similar to the search term provided by the user. This endpoint has the following parameters
NAME
Mandatory
TYPE
DEFAULT
DESCRIPTION
Notes
Key
Yes
String
API Key
SearchTerm
Yes
String
The search term to find. If the LastId is provided, the SearchTerm searches within the results from the LastId.
URL encoded
LastId
No
String
The Id from a previous Find or FindByPosition.
URL encoded
Country
No
String
CAN
The name or ISO 2 or 3 character code for the country to search in. Most country names will be recognised but the use of the ISO country code is recommended for clarity.
LanguagePreference
No
String
en
The 2 or 4 character language preference identifier e.g. (en, en-gb, en-us etc).
MaxSuggestions
No
Integer
7
The maximum number of autocomplete suggestions to return.
It is possible to submit request to this endpoint for free using Canada Post website.
Example request:
https://ws1.postescanada-canadapost.ca/AddressComplete/Interactive/Find/v2.10/json3.ws?Key=<your< API Key comes here>&SearchTerm=390&Country=CAN
Response body
The response consists of Items list with addresses as elements.
Pay attention, as described in the possible flows above, if returned address element contains Next field with the value Find it means that to get detailed address there is a need to issue additional Find request with the LastId set with the Id value from that address element.
For example,
First Find request with Search Term: 234 Drinkwater St
The response from the web service is a table containing the elements below. Where no items are found, the response will be empty list (although all endpoints specify the columns). If an error occurs, the response will be an error table instead.
NAME
TYPE
DESCRIPTION
VALUES
EXAMPLE
Id
String
The Id to be used as the LastId with the Find method.
CAN|PR|X247361852|E|0|0
Text
String
The found item.
2701 Riverside Dr, Ottawa, ON
Highlight
String
A list of number ranges identifying the characters to highlight in the Text response (zero-based start position and end).
0-2,6-4
Cursor
Integer
A zero-based position in the Text response indicating the suggested position of the cursor if this item is selected. A -1 response indicates no suggestion is available.
0
Description
String
Descriptive information about the found item, typically if it’s a container.
Since we are talking about web service here the errors that it returns are returned with 200 response while the error itself is contained in the body of the response. Details about all possible errors can be found on Canda Post website.
Example of an error response
For example, the general error below is shown when the API Key is not assigned to get requests from a particular URL.
{
"Items": [
{
"Error": "5",
"Description": "Request not allowed from this URL",
"Cause": "The request was disallowed from the URL.",
"Resolution": "Check the security settings on the key first. If they look fine, please contact
support as it may be from a URL on our blacklist."
}
]
}
Retrieve endpoint returns the full address details based on the Id, which is returned as a result of the Find request.
As was mentioned in the possible flows section above, initial Find request returns a list of addresses that closely match the search term used by the user. Each address contains an Id field. This Id should be used to issue Retrieve request. You can try the request for free on Canada Post website.
Parameters
Each request to the web service requires the following parameters. You can create any number of keys, each of which can be reported on individually and have specific security settings.
NAME
TYPE
Mandatory
DESCRIPTION
DEFAULT
EXAMPLE
Notes
Key
String
Yes
The key to use to authenticate to the service.
AA11-AA11-AA11-AA11
Id
String
Yes
The Id from a Find method to retrieve the details for.
The response consists of Items list with two elements: first element is the address in English, second element is the address in French.
Response Fields
The response from the web service is a table containing the elements below. Where no items are found, the response will be empty list (although all endpoints specify the columns). If an error occurs, the response will be an error table instead.
Below are the errors specific to this web service. If an error occurs, an error table like the one below (but containing a single row) will be returned. (Developers should test for a 4-column table with columns “Error”, “Description”, “Cause” and “Resolution”.)
ERROR
DESCRIPTION
CAUSE
RESOLUTION
1001
Id Invalid
The Id parameter supplied was invalid.
Try again, using only IDs from the Find services.
1002
Not Available
This record contains data that is not available on your account.
Please contact support to upgrade your account.
Example of an error response
For example, the general error below is shown when the account has no money balance to allow for queries.
{
"Items": [
{
"Error": "3",
"Description": "Account out of credit",
"Cause": "Your account is either out of credit or has insufficient credit to service this request.",
"Resolution": "Please check your account balance and top it up if necessary."
}
]
}
References
This is a github repository containing React with classes implementation of two possible ways to integrate with Canada Post AddressComplete API as was explained before. Pay attention that to install the dependencies there is a need to use yarn.