Prev: Win32 non blocking console input?
Next: hugi compo #29
From: Rod Pemberton on 4 Dec 2008 05:00 <NathanCBaker(a)gmail.com> wrote in message news:81d0f2a8-5e34-4815-bc29-9aa56349cfe2(a)l39g2000yqn.googlegroups.com... > On Dec 2, 5:00 am, "Rod Pemberton" <do_not_h...(a)nohavenot.cmm> wrote: > > Hmm, dword, boolean, int32... Is there a difference between "dword" and > > "int32" in HLA? Why?!?!... Why are there both differently sized "words" > > and differently sized "ints"? I'm assuming both are multiples of 8-bit > > bytes. Yes? Is one unsigned and the other signed!?!?! (Horror of horrors! > > Please don't say "yes"...) If so, which is which? No way to tell from > > that. > > > > dword = dword > int32 = signed > uns32 = unsigned > boolean = dword (if I recall correctly) 3 or 4 32-bit types? Why? That completely nullifies the use of a typesystem. It's like using "void *" to prevent casting in C or to intentionally bypass the typesystem... > > What exactly is a "boolean" in regards to assembly? Does this mean every > > time "down" is used it gets logical and-ed with 0x01 ? What a waste... > > Maybe he should add unions like C - then you get 8 booleans per byte - but > > everything still gets an implicit "and"... > > > > Does the C standard specify the the implementation must guarantee "8 > booleans per byte", No. Ok, I didn't look this all up again. It's from memory... IIRC, the C standard requires a "C char" must be large enough to represent the entire character set. It must be at least the size of the minimum addressable number of bits, which, IIRC, is called a "C byte". If a "C byte" is too small to represent the entire character set, a "C char" can also be multiple "C bytes". However, minimum sizes of types are declared elsewhere, with 8 bits, IIRC, being the smallest size for a "C char". > Does the C standard specify the the implementation must guarantee "8 > booleans per byte", > or is that simply an artifact of compiler- > designers' choices? No. A "byte" as 8-bits, AFAIK, is/was a de-facto standard for microprocessors. I'm sure their are some other examples, but the C specifications are the only place I'm aware of that formally define a "byte" as something other than 8-bits. > > Hey, he says it's not C, therefore it should look more like OOP C++, i.e., > > action.object . The hodge-podge, everything-from-everywhere, language > > design of HLA is really irksome. Don't you think so? > > > > The hodge-podge, everything-from-everywhere, language > design of Python is really irksome. Don't you think so? Never used it... I've got no idea what it looks like. > The hodge-podge, everything-from-everywhere, language > design of Ruby is really irksome. Don't you think so? Never used it... I've looked at it. But, what I saw looked much like C++ OOP. It was all action.object or object.action. And, IIRC, there where certain default actions that each type had, like, say .zero to zero a number type, or .nl to emit a newline on a output type, etc. > The hodge-podge, everything-from-everywhere, language > design of Java is really irksome. Don't you think so? Never used it... But, I'm sure I heard that it's a subset of C. So, I'd probably have to say "no." > > > if( esi = 0 ) then > > > > I'll have to assume equality and not assignment... Use of "=" for > > assignment is likely to permanently braindamage HLA programmers when they > > move on to C or Pascal. Superb syntax choice, not! > > Assignment in Nasm is: mov eax, 42 Sorry, the usage in first sentence was correct. The second should've said "equality". I.e., equality is "==" or ":=" in C or Pascal, using "=" for equality instead of assignment will cause mental problems. > > > endfor; > > > > For want of braces, to terminate a for()... I'm forced to type five more. > > I actually appreciate the readability of "endfor;", "endif;", and the > like. It seems to me to be a block language, so block terminators, like the more common "wend" for while, "fi" for if, "esac" for case, BEGIN END etc., are basically required. > A couple months ago, I had the devil of the time attempting to > enhance a semi-complicated piece of Ruby code when I tried to locate > the end of a 'while' loop hidden among a bunch of nested if blocks. > This is what I saw [replacing spaces with "." in case you're not using > a fixed-width font]: > > ............end > ..........end > ........end > ......end > ....end > ..end > end > > One of those in the middle was the 'end' associated with the 'while'. So? It looks well indented... You should've been able to align the columns. If not, before the entire block, set somevar=0. Inside the "while", set somevar=1. Prior to each "end", check somevar for 1 and if so, print a message specific to that "end". From past conversations, it seems that these problems seem to plague you. You need to learn to use "printf" or it's equivalent as your only debugger. > I probably would have pulled out my hair if I had to deal with this: > > )))))))))))))) }}}}}}}}}}}}}} They'd have been indented properly in well written code... > reverse the loop.... > > test al, -1 > jz @F > dec ecx > jnz @B HLA supports FASM syntax in addition to "twisted NASM"?... > > > stdin.getc(); > > > > Is there a need for () on getc here? Is there any other place a char can > > come from other than the stated stdin? I.e., I don't think this is legal: > > > > stdin.getc(myfile); > > > > A lot of the StdLib functions are re-use in other namespaces. So, > there really is something like: > > fileio.getc( myfile ); > > ...because we *do* have to specify the file handle when accessing > anything other than stdin, stdout, and stderr. In which case, "fileio" is the problem. "myfile", stdin, stdout, and stderr are file handles. "fileio" is not a file handle. "fileio" is a function modifier. It converts "getc" to the equivalent of C's file getc, i.e., "fgetc"... I.e., you should *either* be able to use the file directly as a file handle: myfile.getc(); //Again, is there a need for () on getc here? *Or*, you should be have a different functions to represent "getting" a character from a file instead of stdio: getc; // implicitly from stdin putc; // implicitly to stdout fgetc(myfile); // from a file "myfile" or explicitly stdin fputc(myfile); // to a file "myfile" or explicitly stdout I'm just pointing out that the HLA I've seen seems to lack a consistent methodology or ideology for it's language syntax. In the one case, it's file_handle.getc(no_arg) and in the other it's getc_function_modifier.getc(file_handle). Using a file_handle in two different locations like that both with getc() must complicate the grammar. > > Coal for Randall... > > > > A programmer's manual for Rod. Apparently not, since I still don't know what values "true" and "false" represent. I don't know whether booleans are logically anded with one. I don't know how "edx" became a boolean without a declaration as such or why it would be legal to use it in that way if HLA has any type system at all. And, I still don't know why HLA has, apparently, at least 3 32-bit types... Rod Pemberton
From: Frank Kotler on 4 Dec 2008 04:37 NathanCBaker(a)gmail.com wrote: > On Dec 2, 5:41 am, Herbert Kleebauer <k...(a)unibwm.de> wrote: >> NathanCBa...(a)gmail.com wrote: >>> On Dec 1, 7:33 am, Herbert Kleebauer <k...(a)unibwm.de> wrote: >>>> Does HLA now support optimization or do you really use the div instruction to >>>> dived by 4? >>> Optimization!?!? You want to optimize a simple console game?? I >>> think an explicit division instruction enhances the readability -- >> If you want readability, use a HLL (and then you also get speed >> because the compiler doesn't use the div instruction when you >> write /4 in your source). >> > > In psuedo: > > func y ( a, b, c ) { > return a + ( b / c ) > } > > Will the HLL compiler generate code such that in the event that c = 4, > the code will not execute the div instruction?? The compiler doesn't know what's in "c", of course - would have to be done at runtime... As you know, I've been bangin' my head against 64-bit integers in 32-bit C/asm on the Nasm Forum. For the hell of it, I thought to see what C made of: long long int divby4(long long int k) { return k/4LL; } Well... (with "-O3" and "-fomit-frame-pointer" - Agner Fog's "objconv -fnasm"): ; Disassembly of file: divby4.o ; Tue Dec 2 06:13:10 2008 ; Mode: 32 bits ; Syntax: YASM/NASM ; Instruction set: 80386 global divby4 SECTION .text align=16 execute ; section number 1, code divby4: ; Function begin push ebx ; 0000 _ 53 mov ebx, dword [esp+0CH] ; 0001 _ 8B. 5C 24, 0C mov ecx, dword [esp+8H] ; 0005 _ 8B. 4C 24, 08 mov edx, ebx ; 0009 _ 89. DA mov eax, ebx ; 000B _ 89. D8 sar edx, 31 ; 000D _ C1. FA, 1F ; Filling space: 2H ; Filler type: mov with same source and destination ; db 89H, 0D2H ALIGN 2 sar edx, 31 ; 0012 _ C1. FA, 1F mov eax, edx ; 0015 _ 89. D0 mov eax, edx ; 0017 _ 89. D0 shr eax, 30 ; 0019 _ C1. E8, 1E xor edx, edx ; 001C _ 31. D2 add eax, ecx ; 001E _ 01. C8 adc edx, ebx ; 0020 _ 11. DA pop ebx ; 0022 _ 5B shrd eax, edx, 2 ; 0023 _ 0F AC. D0, 02 sar edx, 2 ; 0027 _ C1. FA, 02 ret ; 002A _ C3 ; divby4 End of function SECTION .data align=4 noexecute ; section number 2, data SECTION .bss align=4 noexecute ; section number 3, bss Or in "-S" format from gcc: .file "divby4.c" .text .p2align 4,,15 ..globl divby4 .type divby4, @function divby4: pushl %ebx movl 12(%esp), %ebx movl 8(%esp), %ecx movl %ebx, %edx movl %ebx, %eax sarl $31, %edx movl %edx, %edx sarl $31, %edx movl %edx, %eax movl %edx, %eax shrl $30, %eax xorl %edx, %edx addl %ecx, %eax adcl %ebx, %edx popl %ebx shrdl $2, %edx, %eax sarl $2, %edx ret .size divby4, .-divby4 .ident "GCC: (GNU) 4.2.1" .section .note.GNU-stack,"",@progbits Okay... I guess "k/4" is more readable... .... sar edx, 31 mov edx, edx sar edx, 31 .... Okay... Y'know, I'm likin' "div" better and better! :) Best, Frank
From: Herbert Kleebauer on 4 Dec 2008 07:06 Sorry, if this shows up twice, but the first post didn't seem to get through. NathanCBaker(a)gmail.com wrote: > > On Dec 2, 5:41 am, Herbert Kleebauer <k...(a)unibwm.de> wrote: > > NathanCBa...(a)gmail.com wrote: > > > On Dec 1, 7:33 am, Herbert Kleebauer <k...(a)unibwm.de> wrote: > > > > Does HLA now support optimization or do you really use the div instruction to > > > > dived by 4? > > > > > Optimization!?!? You want to optimize a simple console game?? I > > > think an explicit division instruction enhances the readability -- > > > > If you want readability, use a HLL (and then you also get speed > > because the compiler doesn't use the div instruction when you > > write /4 in your source). > > > > In psuedo: > > func y ( a, b, c ) { > return a + ( b / c ) > } > > Will the HLL compiler generate code such that in the event that c = 4, > the code will not execute the div instruction?? Let's try: #include <stdio.h> static inline int func(n,i,j,k) unsigned int n,i,j,k; {return n*(i+j)/k;} int main() {unsigned int i,j,k,n; i=14; j=2; k=64; n=getchar(); n=func(n,i,j,k); putchar(n); } The generated assembly code: .section .text .p2align 4,,15 ..globl _main _main: pushl %ebp movl %esp, %ebp pushl %eax pushl %eax andl $-16, %esp call _getchar subl $12, %esp sall $4, %eax shrl $6, %eax pushl %eax call _putchar movl %ebp, %esp popl %ebp ret .ident "GCC: (GNU) 3.3.4" A compiler is like a chess program. There are only a very few people who can compete with it. > So, you agree with me that 'mov( 0, eax )' is better readable? Why should this be better readable than sub.l r0,r0 eor.l r0,r0 We do assembly programming to learn about the instructions and that means, that you also learn that a "eor.l r0,r0" is a shorter opcode than "move.l #0,r0". > > > > You'll need the Randy Hyde x86 processor manual which describes these > > > fancy new machine instructions ( e.g. rand.randomize, mem.alloc, > > > etc. ): > > > > HLA is maybe the most important contribution in killing assembly > > programming (if it really is use for teaching assembly programming > > as Randy claims). > > > > I think the biggest obstacle is lack of interest in detail among the > younger generation... and maybe also a bit of laziness. And that they can get away with HLA when they are forced to learn assembly programming. > Are you trying to say that a C compiler makes a good assembler? Would At least the number of assembly source code lines generated by the compiler is only halve the lines of your source code. > you teach people assembly language by simply teaching them to write C > code? No ,I would do it in real assembly (not a single library call): The binary: @echo off echo hD1X-s0P_kUHP0UxGWX4ax1y1ieimnfeinklddmemkjanmndnadmndnpbbn>puzzle.com echo hhpbbnpljhoxolnhaigidpllnbkdnhlkfhlflefblffahfUebdfahhfkokh>>puzzle.com echo adP1k/1Ta4Hmax(a)e1///a4ckb////QaNBGU1ax/mbNqeax/ma4YN2aj1mdC>>puzzle.com echo RVPqUt2FRWPKAPPajc9///Mai3////MKiE////Q5faVyj////b8SxkqUNcH>>puzzle.com echo @////g9M5ug1///MaGphhNcr6////DlNq23K@////DVF65wE5R4lnRox3Dn>>puzzle.com echo FbJfzBg6M5uz0///gCdaZMqaBMu3MzkAEbuaRsmbNqW2We///kNaZMUc9//>>puzzle.com echo /QaN6D7e1///w01AkMKunxzzzPKWNPqU0HUx0n/RtiSnaZMqaBMuE7bff@g>>puzzle.com echo N8ahN25A3/aDEn0uuoOKA/P5Ms1kDbp7JYkFi0/EAPrQ7mhGC0PKMEGb0aV>>puzzle.com echo vzzzzzaBgNUV@//RKXIF16t5//8iQnV7L1t3QR4MKMEOqkomInVkIn.....>>puzzle.com The source: @=$100 move.l #'| 00'-('a'-'0'-10),r1 eor.l r2,r2 move.l #feld,r6 _20: add.l #'a'-'0'-10,r1 _10: lea.l (r1,r2),r0 bswap.l r0 move.l r0,(r6)+-{s1} bswap.l r0 inc.l r2 cmpq.l #10,r2 blo.b _10 beq.b _20 cmpq.l #16,r2 bne.b _10 eor.l r3,r3 loop: move.l #feld,r5 move.l #4,r1 _20: move.l #16,r2 _10: move.b (r5)+-,r0 bsr.l putc dbf.l r2,_10 move.b #13,r0 bsr.l putc move.b #10,r0 bsr.l putc dec.l r1 bne.b _20 _30: bsr.l getc cmp.b #'q',r0 beq.l exit cmp.b #'a',r0 beq.b _a10 cmp.b #'d',r0 beq.b _d10 cmp.b #'w',r0 beq.b _w10 cmp.b #'s',r0 beq.b _s10 br.b _30 _x10: move.b #$07,r0 bsr.l putc br.b loop _a10: move.l r3,r2 subq.l #4,r2 tst.b #%1100,r3 beq.b _x10 _a20: exg.l r2,r3 move.l feld(r3),r0 move.l r0,feld(r2) move.l #'00 |',feld(r3) br.l loop _d10: move.l r3,r2 addq.l #4,r2 tst.b #%1100,r2 beq.b _x10 br.b _a20 _w10: move.l r3,r2 subq.l #16,r2 bcs.b _x10 br.b _a20 _s10: move.l r3,r2 addq.l #16,r2 cmp.b #64,r2 bhs.b _x10 br.b _a20 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; implementation of getc, putc and exit ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; getc: eor.l r0,r0 movem.l r0-r7,-(sp) move.w #$3f00,r0 lea.w 28.b(r7),r1 move.w #1,r2 eor.w r3,r3 trap #$21 bcs.b exit cmp.w r0,r2 movem.l (sp)+,r0-r7 beq.b _10 move.l #-1,r0 _10: rts.l putc: movem.l r0-r7,-(sp) move.w #$4000,r0 lea.w 28.b(r7),r1 move.w #1,r2 move.w r2,r3 trap #$21 bcs.b exit cmp.w r0,r2 bne.b exit movem.l (sp)+,r0-r7 rts.l exit: move.b #$4c,m0 trap #$21 even 4 feld: blk.l 16
From: Herbert Kleebauer on 4 Dec 2008 05:53 NathanCBaker(a)gmail.com wrote: > > On Dec 2, 5:41 am, Herbert Kleebauer <k...(a)unibwm.de> wrote: > > NathanCBa...(a)gmail.com wrote: > > > On Dec 1, 7:33 am, Herbert Kleebauer <k...(a)unibwm.de> wrote: > > > > Does HLA now support optimization or do you really use the div instruction to > > > > dived by 4? > > > > > Optimization!?!? You want to optimize a simple console game?? I > > > think an explicit division instruction enhances the readability -- > > > > If you want readability, use a HLL (and then you also get speed > > because the compiler doesn't use the div instruction when you > > write /4 in your source). > > > > In psuedo: > > func y ( a, b, c ) { > return a + ( b / c ) > } > > Will the HLL compiler generate code such that in the event that c = 4, > the code will not execute the div instruction?? Let's try: #include <stdio.h> static inline int func(n,i,j,k) unsigned int n,i,j,k; {return n*(i+j)/k;} int main() {unsigned int i,j,k,n; i=14; j=2; k=64; n=getchar(); n=func(n,i,j,k); putchar(n); } The generated assembly code: .section .text .p2align 4,,15 ..globl _main _main: pushl %ebp movl %esp, %ebp pushl %eax pushl %eax andl $-16, %esp call _getchar subl $12, %esp sall $4, %eax shrl $6, %eax pushl %eax call _putchar movl %ebp, %esp popl %ebp ret .ident "GCC: (GNU) 3.3.4" A compiler is like a chess program. There are only a very few people who can compete with it. > So, you agree with me that 'mov( 0, eax )' is better readable? Why should this be better readable than sub.l r0,r0 eor.l r0,r0 We do assembly programming to learn about the instructions and that means, that you also learn that a "eor.l r0,r0" is a shorter opcode than "move.l #0,r0". > > > > You'll need the Randy Hyde x86 processor manual which describes these > > > fancy new machine instructions ( e.g. rand.randomize, mem.alloc, > > > etc. ): > > > > HLA is maybe the most important contribution in killing assembly > > programming (if it really is use for teaching assembly programming > > as Randy claims). > > > > I think the biggest obstacle is lack of interest in detail among the > younger generation... and maybe also a bit of laziness. And that they can get away with HLA when they are forced to learn assembly programming. > Are you trying to say that a C compiler makes a good assembler? Would At least the number of assembly source code lines generated by the compiler is only halve the lines of your source code. > you teach people assembly language by simply teaching them to write C > code? No ,I would do it in real assembly (not a single library call): The binary: @echo off echo hD1X-s0P_kUHP0UxGWX4ax1y1ieimnfeinklddmemkjanmndnadmndnpbbn>puzzle.com echo hhpbbnpljhoxolnhaigidpllnbkdnhlkfhlflefblffahfUebdfahhfkokh>>puzzle.com echo adP1k/1Ta4Hmax(a)e1///a4ckb////QaNBGU1ax/mbNqeax/ma4YN2aj1mdC>>puzzle.com echo RVPqUt2FRWPKAPPajc9///Mai3////MKiE////Q5faVyj////b8SxkqUNcH>>puzzle.com echo @////g9M5ug1///MaGphhNcr6////DlNq23K@////DVF65wE5R4lnRox3Dn>>puzzle.com echo FbJfzBg6M5uz0///gCdaZMqaBMu3MzkAEbuaRsmbNqW2We///kNaZMUc9//>>puzzle.com echo /QaN6D7e1///w01AkMKunxzzzPKWNPqU0HUx0n/RtiSnaZMqaBMuE7bff@g>>puzzle.com echo N8ahN25A3/aDEn0uuoOKA/P5Ms1kDbp7JYkFi0/EAPrQ7mhGC0PKMEGb0aV>>puzzle.com echo vzzzzzaBgNUV@//RKXIF16t5//8iQnV7L1t3QR4MKMEOqkomInVkIn.....>>puzzle.com The source: @=$100 move.l #'| 00'-('a'-'0'-10),r1 eor.l r2,r2 move.l #feld,r6 _20: add.l #'a'-'0'-10,r1 _10: lea.l (r1,r2),r0 bswap.l r0 move.l r0,(r6)+-{s1} bswap.l r0 inc.l r2 cmpq.l #10,r2 blo.b _10 beq.b _20 cmpq.l #16,r2 bne.b _10 eor.l r3,r3 loop: move.l #feld,r5 move.l #4,r1 _20: move.l #16,r2 _10: move.b (r5)+-,r0 bsr.l putc dbf.l r2,_10 move.b #13,r0 bsr.l putc move.b #10,r0 bsr.l putc dec.l r1 bne.b _20 _30: bsr.l getc cmp.b #'q',r0 beq.l exit cmp.b #'a',r0 beq.b _a10 cmp.b #'d',r0 beq.b _d10 cmp.b #'w',r0 beq.b _w10 cmp.b #'s',r0 beq.b _s10 br.b _30 _x10: move.b #$07,r0 bsr.l putc br.b loop _a10: move.l r3,r2 subq.l #4,r2 tst.b #%1100,r3 beq.b _x10 _a20: exg.l r2,r3 move.l feld(r3),r0 move.l r0,feld(r2) move.l #'00 |',feld(r3) br.l loop _d10: move.l r3,r2 addq.l #4,r2 tst.b #%1100,r2 beq.b _x10 br.b _a20 _w10: move.l r3,r2 subq.l #16,r2 bcs.b _x10 br.b _a20 _s10: move.l r3,r2 addq.l #16,r2 cmp.b #64,r2 bhs.b _x10 br.b _a20 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; implementation of getc, putc and exit ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; getc: eor.l r0,r0 movem.l r0-r7,-(sp) move.w #$3f00,r0 lea.w 28.b(r7),r1 move.w #1,r2 eor.w r3,r3 trap #$21 bcs.b exit cmp.w r0,r2 movem.l (sp)+,r0-r7 beq.b _10 move.l #-1,r0 _10: rts.l putc: movem.l r0-r7,-(sp) move.w #$4000,r0 lea.w 28.b(r7),r1 move.w #1,r2 move.w r2,r3 trap #$21 bcs.b exit cmp.w r0,r2 bne.b exit movem.l (sp)+,r0-r7 rts.l exit: move.b #$4c,m0 trap #$21 even 4 feld: blk.l 16
From: Frank Kotler on 4 Dec 2008 07:06
NathanCBaker(a)gmail.com wrote: .... >> Compiling "sliders.hla" to "sliders.obj" >> Error in file "os.hhf" at line 5 >> syntax error, unexpected namespaceTkn, expecting DoOneValStmt. >> Near: << namespace >> >> > > This hints at a copy-N-paste error. { looking back at my original > post, yep, I goofed! } Add a "program fifteen;" line at the beginning > just above the "#include" directive. Of course!!! Why didn't I figure that out from the error message? :) (This is "experience" - "recognizing an error when you make it again". Like when I got a column of '%' characters from Michael's "maxofthree", I said to myself "this doesn't look like an assembly language error to me"...) Pretty cool! Too bad we can't use the arrow keys, and too bad we have to hit "enter" every time. Interesting to note that in a GUI, where we get "events" or "messages", this is actually easier to do! Well, sometimes procrastination pays off. You saved me having to reinstall HLA! Now that I can assemble it, I can disassemble it and see what it "really" says. Hmmm, Agner's objconv gets a few "Error: this is unlikely to be code"... and some other errors... I suspect it's not liking those length-prefixed strings(?). (IIRC, RosAsm's disassembler didn't like 'em, either) Ah, yes... this is the version of HLA that links in the dynamic linker, whether we use it or not, so we can call libc if we care to... Sigh. Well, it wasn't exactly "lean and mean" code anyway... .... FILEIO_PUTH8SIZE: push ebp ; 08049A50 _ 55 mov ebp, esp ; 08049A51 _ 89. E5 sub esp, 4116 ; 08049A53 _ 81. EC, 00001014 Kind of a lot, innit? What in hell we need a 4k buffer to display one hex byte for??? Oh, I see, in case we want to left/right justify it in a really big field... (speaking of "quiet", hope Wolfgang's okay! He would consider this "stack abuse", I think.) I suppose I should look at Herbert's "readable" version, too... Best, Frank |