; m12_demo.asm
; @topic W140160 Lab M12, calling C standard library functions
; @brief Calling C strlen(&nbsp;) and strncpy(&nbsp;) from Assembly

.586P
.MODEL FLAT     ; Flat memory model
option casemap:none ; Treat labels as case-sensitive

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Add C run-time libraries
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; see https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=vs-2019
; The Universal CRT (UCRT) contains the functions and globals
; exported by the standard C99 CRT library. The UCRT is now
; a Windows component, and ships as part of Windows 10.
includelib libucrt.lib

; other C run-time libraries:
; includelib libcmt.lib
; includelib libvcruntime.lib
; includelib legacy_stdio_definitions.lib

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; these procedures are part of the C standard library
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXTERN _strlen:NEAR
EXTERN _strncpy:NEAR

.const  ; Read-only data segment
        str_hello_world      byte "Hello, World!", 0

.data   ; The data segment
        str_hello_world_copy byte SIZEOF str_hello_world dup(?)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.code   ; Code segment begins
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

_main PROC      ; Beginning of code

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; call strlen to get string length
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; strlen takes one param: the address of the string
    push OFFSET str_hello_world
    call _strlen    ; Get string length. Result is in EAX
    inc eax         ; include null character

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; call strncpy to copy characters
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ; to call _strncpy, we need to prepare its
    ; arguments on the stack according to
    ; C (__cdecl) calling convention. This is the
    ; default calling convention for C and C++ functions.
    ; The arguments are passed right to left:
    ;   char * strncpy ( char * destination, const char * source, size_t num );

    push eax                            ; number of characters to copy
    push OFFSET str_hello_world         ; source
    push OFFSET str_hello_world_copy    ; destination
    call _strncpy ; Copy characters. EAX contains destination address upon return

    xor eax, eax ; EAX = 0 indicates "success" upon return from main()
    ret
    
_main ENDP
END _main       ; Marks the end of the module and sets the program entry point label