; =================== source-file: _lastmember.asm =====================
;
; Purpose: Returns the last element of a list; if the list is empty, it
; returns the empty list-element. The list can be of any type / domain,
; including real numbers (for which there is a second variant, since real
; number lists in Visual Prolog have 16-byte elements, instead of 12-byte
; elements.

    IDEAL
P586
    MODEL   flat
    CODESEG
ALIGN 4

    public _lastmember_0
    public _lastmember_1
   
PROC _lastmember_0 near
    mov ecx,[esp+4] ; input-list.....................ARG-1(i)
    mov edx,ecx     ; initialize EDX as last_element pointer
    mov ah,2            ; prepare AH = 2 (end-element flag)
    push    ebx         ; preserve EBX
    mov    ebx,8       ;
@@p1:
    mov al,[byte ptr ecx]  ; put the "element-type indicator" in AL
    cmp    al,ah           ; compare with 2 (end-of-list indicator)
    jz @@xx                ; if end of list, then exit!   
; ---------------------------
     mov    edx,ecx     ; else, store the current list_pointer
    mov    ecx,[ecx+ebx]   ; make ECX = next list-element-pointer
    jmp short @@p1         ; repeat the loop
; ===========================
@@xx:    shr    ebx,1       ; make ebx = 4
    mov    eax,[edx+ebx]   ;
    pop ebx                 ; restore EBX
    retn
ENDP _lastmember_0

PROC _lastmember_1 near     ; for REAL-lists, only!
    mov ecx,[esp+4]     ; input-list.....................ARG-1(i)
    mov edx,ecx         ; initialize EDX as last_element pointer
    mov ah,2                ; prepare AH = 2 (end-element flag)
    push    ebx             ; preserve EBX
    mov    ebx,12          ; REAL numbers require 12-byte jumps
@@p1:
    mov al,[byte ptr ecx]  ; put the "element-type indicator" in AL
    cmp    al,ah           ; compare with 2 (end-of-list indicator)
    jz @@xx                ; if end of list, then exit!   
; ---------------------------
     mov    edx,ecx     ; else, store the current list_pointer
    mov    ecx,[ecx+ebx]   ; make ECX = next list-element-pointer
    jmp short @@p1         ; repeat the loop
; ===========================
@@xx:   
    fld [qword ptr edx+4]   ; return the real number in address [edx+4]
    pop ebx                 ; restore EBX
    retn
ENDP _lastmember_1

    end
   
; ================= VISUAL PROLOG TEST-PROGRAM: ==================
GLOBAL DOMAINS
 ILIST = INTEGER*
 RLIST = REAL*
 SLIST = STRING*

GLOBAL PREDICATES
 INTEGER lastmember(ILIST) -(i) language c %_lastmember_0
 REAL lastmember(RLIST) -(i) language c %_lastmember_1
 STRING lastmember(SLIST) -(i) language c as "_lastmember_0"
% PNT lastmember(PNTLIST) -(i) language c as "_lastmember_0" (etc.)

GOAL
  List2 = [22,33,44,55,66,77], LastINT = lastmember(List2),
  write("\nfor an integer-list: ",List2,", LastINT = ",LastINT), nl,
  List1 = ["this","that","ok","fourth","end"], LastSTR = lastmember(List1),
  write("\nfor a string-list: ",List1,", LastSTR = \"",LastSTR,"\"\n"),
  List3 = [2.1,2.3,4.1,5.67], LastREAL = lastmember(List3),
  write("\nfor a Real-list: ",List3,", LastREAL = ",LastREAL), nl,
  readchar(CHx), CHx = '\27', !.

; **************  "32-bit Assembly Language Extensions for Visual Prolog" ****************
; Written by George A. Stathis (c) 2005,       E-mail: omadeon@yahoo.com,  gstathis@enm.gr
; URL: http://www.omadeon.com/asm    Company: ENB Ltd.     Company site: http://www.enb.gr
; **** Use of this source-code is unrestricted provided that the author is mentioned. ****