Jump anywhere: Difference between revisions
Content added Content deleted
Puppydrum64 (talk | contribs) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 29: | Line 29: | ||
===Direct Jump=== |
===Direct Jump=== |
||
This is strictly a one-way trip, just like GOTO in BASIC. The program counter will be set to the specified address or label. This technique is limited to constants. In other words, a direct jump cannot be altered at runtime (self-modifying code notwithstanding) |
This is strictly a one-way trip, just like GOTO in BASIC. The program counter will be set to the specified address or label. This technique is limited to constants. In other words, a direct jump cannot be altered at runtime (self-modifying code notwithstanding) |
||
< |
<syntaxhighlight lang="6502asm">JMP PrintChar ; jump to the label "PrintChar" where a routine to print a letter to the screen is located.</syntaxhighlight> |
||
===Indirect Jump=== |
===Indirect Jump=== |
||
This method is a form of the "computed GOTO" and lets you jump to an address stored in a pair of memory addresses. The least effective way to do this is as follows: |
This method is a form of the "computed GOTO" and lets you jump to an address stored in a pair of memory addresses. The least effective way to do this is as follows: |
||
< |
<syntaxhighlight lang="6502asm">lda #<PrintChar ;load into A the low byte of the address that PrintChar references. |
||
sta $00 |
sta $00 |
||
lda #>PrintChar ;load into A the high byte of the address that PrintChar references. |
lda #>PrintChar ;load into A the high byte of the address that PrintChar references. |
||
sta $01 ;these need to be stored low then high because the 6502 is a little-endian cpu |
sta $01 ;these need to be stored low then high because the 6502 is a little-endian cpu |
||
JMP ($00) ;dereferences to JMP PrintChar</ |
JMP ($00) ;dereferences to JMP PrintChar</syntaxhighlight> |
||
The above example is just the same as a direct jump but more complicated for no added benefit. To actually use an indirect jump correctly, the input needs to be variable. Here's one way to do that: |
The above example is just the same as a direct jump but more complicated for no added benefit. To actually use an indirect jump correctly, the input needs to be variable. Here's one way to do that: |
||
< |
<syntaxhighlight lang="6502asm">JumpTable_Lo: db <PrintChar, <WaitChar, <ReadKeys, <MoveMouse ;each is the low byte of a memory address |
||
JumpTable_Hi: db >PrintChar, >WaitChar, >ReadKeys, >MoveMouse ;each is the high byte of a memory address |
JumpTable_Hi: db >PrintChar, >WaitChar, >ReadKeys, >MoveMouse ;each is the high byte of a memory address |
||
Line 48: | Line 48: | ||
lda JumpTable_Hi,x |
lda JumpTable_Hi,x |
||
sta $11 |
sta $11 |
||
JMP ($0010)</ |
JMP ($0010)</syntaxhighlight> |
||
Depending on the value of x, you will be taken to a different procedure. Once again, this is a one-way jump and you can't return. |
Depending on the value of x, you will be taken to a different procedure. Once again, this is a one-way jump and you can't return. |
||
Line 54: | Line 54: | ||
Another way to do this is with a "jump block." |
Another way to do this is with a "jump block." |
||
< |
<syntaxhighlight lang="6502asm">.org $8000 |
||
JMP PrintChar |
JMP PrintChar |
||
JMP WaitChar |
JMP WaitChar |
||
JMP ReadKeys |
JMP ReadKeys |
||
JMP MoveMouse |
JMP MoveMouse |
||
</syntaxhighlight> |
|||
</lang> |
|||
Each jump instruction on the 6502 takes up 3 bytes: one for the JMP command itself, and two for the destination. Knowing this, we can use a variable that is a multiple of 3 to take us to the desired location. Let's pretend X is such a variable, and this routine lets us JMP to the "next" routine. |
Each jump instruction on the 6502 takes up 3 bytes: one for the JMP command itself, and two for the destination. Knowing this, we can use a variable that is a multiple of 3 to take us to the desired location. Let's pretend X is such a variable, and this routine lets us JMP to the "next" routine. |
||
< |
<syntaxhighlight lang="6502asm">lda $80 |
||
sta $21 |
sta $21 |
||
txa |
txa |
||
Line 68: | Line 68: | ||
adc #$03 |
adc #$03 |
||
sta $20 |
sta $20 |
||
JMP ($0020)</ |
JMP ($0020)</syntaxhighlight> |
||
If X was 0, the JMP takes us to WaitChar. |
If X was 0, the JMP takes us to WaitChar. |
||
Line 80: | Line 80: | ||
The 65c02, which was used in the Apple II and the Atari Lynx, can perform an indirect jump offset by X. This can be used to perform the above technique with much less setup. |
The 65c02, which was used in the Apple II and the Atari Lynx, can perform an indirect jump offset by X. This can be used to perform the above technique with much less setup. |
||
< |
<syntaxhighlight lang="6502asm">JumpTable: |
||
word PrintChar |
word PrintChar |
||
word PrintString |
word PrintString |
||
Line 86: | Line 86: | ||
ldx #$02 |
ldx #$02 |
||
JMP (JumpTable,x) ;dereferences to JMP PrintString</ |
JMP (JumpTable,x) ;dereferences to JMP PrintString</syntaxhighlight> |
||
Your index needs to be a multiple of 2 for this to work, most of the time you'll use <code>ASL A</code> then <code>TAX</code>to double your index prior to performing the indirect jump. |
Your index needs to be a multiple of 2 for this to work, most of the time you'll use <code>ASL A</code> then <code>TAX</code>to double your index prior to performing the indirect jump. |
||
Line 94: | Line 94: | ||
Unfortunately, you cannot simply replace "JMP" in the above example with "JSR" as that is not a valid command. What you have to do instead is a bit trickier. One way to accomplish this is with a "Return Table." Let's rewrite JumpTable_Lo and JumpTable_Hi in that format. |
Unfortunately, you cannot simply replace "JMP" in the above example with "JSR" as that is not a valid command. What you have to do instead is a bit trickier. One way to accomplish this is with a "Return Table." Let's rewrite JumpTable_Lo and JumpTable_Hi in that format. |
||
< |
<syntaxhighlight lang="6502asm">ReturnTable: dw PrintChar-1,WaitChar-1,ReadKeys-1,MoveMouse-1</syntaxhighlight> |
||
For this example, assume that all of those labels are subroutines that end in an RTS instruction. This method won't work otherwise. Once your return table is defined, you need some sort of variable that allows you to index into that table (i.e. select a subroutine to use). |
For this example, assume that all of those labels are subroutines that end in an RTS instruction. This method won't work otherwise. Once your return table is defined, you need some sort of variable that allows you to index into that table (i.e. select a subroutine to use). |
||
We'll assume for the code below that the accumulator contains such a variable right now. |
We'll assume for the code below that the accumulator contains such a variable right now. |
||
< |
<syntaxhighlight lang="6502asm"> |
||
;execution is currently here |
;execution is currently here |
||
JSR UseReturnTable ;the address just after this label is pushed onto the stack. |
JSR UseReturnTable ;the address just after this label is pushed onto the stack. |
||
Line 114: | Line 114: | ||
RTS ;this "RTS" actually takes you to the desired subroutine. |
RTS ;this "RTS" actually takes you to the desired subroutine. |
||
;The top two bytes of the stack are popped, the low byte is incremented by 1, |
;The top two bytes of the stack are popped, the low byte is incremented by 1, |
||
;and this value becomes the new program counter.</ |
;and this value becomes the new program counter.</syntaxhighlight> |
||
Now all of that was a bit confusing wasn't it? Essentially this "abuses" the following concepts: |
Now all of that was a bit confusing wasn't it? Essentially this "abuses" the following concepts: |
||
Line 139: | Line 139: | ||
In addition, for nearby subroutines, <code>BSR</code> can be used in place of <code>JSR</code> to save data. There is also <code>BRA</code> (branch always) for unconditional local jumping, which the original 6502 didn't have. |
In addition, for nearby subroutines, <code>BSR</code> can be used in place of <code>JSR</code> to save data. There is also <code>BRA</code> (branch always) for unconditional local jumping, which the original 6502 didn't have. |
||
< |
<syntaxhighlight lang="68000devpac">bra foo |
||
nop ;execution will never reach here |
nop ;execution will never reach here |
||
foo: |
foo: |
||
Line 146: | Line 146: | ||
BGE D1_Is_Greater_Than_Or_Equal_To_D0 |
BGE D1_Is_Greater_Than_Or_Equal_To_D0 |
||
; your code for what happens when D1 is less than D0 goes here |
; your code for what happens when D1 is less than D0 goes here |
||
D1_Is_Greater_Than_Or_Equal_To_D0:</ |
D1_Is_Greater_Than_Or_Equal_To_D0:</syntaxhighlight> |
||
===Absolute Jumps=== |
===Absolute Jumps=== |
||
The 68000 has <code>JMP</code> and <code>JSR</code> for absolute jumping and function calls, respectively. When you <code>JSR</code>, the next <code>RTS</code> you encounter will return the program counter to just after the <code>JSR</code> statement you came from, provided that the return address is still on top of the stack when the <code>RTS</code> is executed. The CPU assumes that the top 4 bytes of the stack are the correct return address, and has no way of knowing if it's wrong. A sequence like this will likely result in a crash or otherwise undefined behavior: |
The 68000 has <code>JMP</code> and <code>JSR</code> for absolute jumping and function calls, respectively. When you <code>JSR</code>, the next <code>RTS</code> you encounter will return the program counter to just after the <code>JSR</code> statement you came from, provided that the return address is still on top of the stack when the <code>RTS</code> is executed. The CPU assumes that the top 4 bytes of the stack are the correct return address, and has no way of knowing if it's wrong. A sequence like this will likely result in a crash or otherwise undefined behavior: |
||
< |
<syntaxhighlight lang="68000devpac">JSR foo: |
||
; this is somewhere far away from the JSR above |
; this is somewhere far away from the JSR above |
||
foo: |
foo: |
||
MOVE.L D0,(SP)+ |
MOVE.L D0,(SP)+ |
||
RTS ;the CPU will "return" to the value that was in D0, not the actual return address.</ |
RTS ;the CPU will "return" to the value that was in D0, not the actual return address.</syntaxhighlight> |
||
This can be abused for our benefit, allowing the programmer to select a subroutine from a list of functions. This trick goes by many names, some of the more common ones are "RTS Trick" or "Ret-poline" (a portmanteau of x86's <code>RET</code> and trampoline. <code>RET</code> is called <code>RTS</code> on the 6502 and 68000) |
This can be abused for our benefit, allowing the programmer to select a subroutine from a list of functions. This trick goes by many names, some of the more common ones are "RTS Trick" or "Ret-poline" (a portmanteau of x86's <code>RET</code> and trampoline. <code>RET</code> is called <code>RTS</code> on the 6502 and 68000) |
||
< |
<syntaxhighlight lang="68000devpac">;For this example, we want to execute "ReadJoystick" |
||
MOVE.W D0,#1 |
MOVE.W D0,#1 |
||
JSR Retpoline |
JSR Retpoline |
||
Line 175: | Line 175: | ||
SubroutineTable: |
SubroutineTable: |
||
DC.L MoveMouse, DC.L ReadJoystick, DC.L ReadKeyboard, DC.L PrintString</ |
DC.L MoveMouse, DC.L ReadJoystick, DC.L ReadKeyboard, DC.L PrintString</syntaxhighlight> |
||
===Indirect Jumps=== |
===Indirect Jumps=== |
||
Line 184: | Line 184: | ||
<code>JCXZ</code> will jump only if the <code>CX</code> register equals 0. This is useful for skipping a loop if <code>CX</code> (the loop counter) is already zero. |
<code>JCXZ</code> will jump only if the <code>CX</code> register equals 0. This is useful for skipping a loop if <code>CX</code> (the loop counter) is already zero. |
||
< |
<syntaxhighlight lang="asm">JCXZ bar |
||
foo: |
foo: |
||
LOOP foo ;subtract 1 from CX, and if CX is still nonzero jump back to foo |
LOOP foo ;subtract 1 from CX, and if CX is still nonzero jump back to foo |
||
bar:</ |
bar:</syntaxhighlight> |
||
<code>LOOP label</code> is the equivalent of <code>DEC CX JNZ label</code> and, as the name implies, is used for looping. You might have heard that <code>DEC CX JNZ label</code> should always be used over <code>LOOP label</code> for better performance. This is only true on later x86-based CPUs - the reasons for <code>LOOP</code>'s poor performance weren't present on the 8086, and as such it's better to use there. |
<code>LOOP label</code> is the equivalent of <code>DEC CX JNZ label</code> and, as the name implies, is used for looping. You might have heard that <code>DEC CX JNZ label</code> should always be used over <code>LOOP label</code> for better performance. This is only true on later x86-based CPUs - the reasons for <code>LOOP</code>'s poor performance weren't present on the 8086, and as such it's better to use there. |
||
Line 195: | Line 195: | ||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
< |
<syntaxhighlight lang="ada"> |
||
procedure Goto_Test is |
procedure Goto_Test is |
||
begin |
begin |
||
Line 245: | Line 245: | ||
end Goto_Test; |
end Goto_Test; |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|ARM Assembly}}== |
=={{header|ARM Assembly}}== |
||
Line 264: | Line 264: | ||
ARM is very unique in that the program counter can be directly loaded as well as influenced by branching. You need to be very careful when doing this, because loading a value into <code>PC</code> that isn't a multiple of 4 will crash the CPU. |
ARM is very unique in that the program counter can be directly loaded as well as influenced by branching. You need to be very careful when doing this, because loading a value into <code>PC</code> that isn't a multiple of 4 will crash the CPU. |
||
< |
<syntaxhighlight lang="arm assembly">MOV PC,R0 ;loads the program counter with the value in R0. (Any register can be used for this) |
||
LDR PC,[R0] ;loads the program counter with the 32-bit value at the memory location specified by R0</ |
LDR PC,[R0] ;loads the program counter with the 32-bit value at the memory location specified by R0</syntaxhighlight> |
||
This sequence of commands can store registers onto the stack, retrieve them, and return all at once. For this to work properly the only difference in the choice of registers can be that you push <code>LR</code> and pop <code>PC</code>. |
This sequence of commands can store registers onto the stack, retrieve them, and return all at once. For this to work properly the only difference in the choice of registers can be that you push <code>LR</code> and pop <code>PC</code>. |
||
< |
<syntaxhighlight lang="arm assembly">PUSH {R0-R12,LR} |
||
POP {R0-R12,PC}</ |
POP {R0-R12,PC}</syntaxhighlight> |
||
If you don't have access to unified syntax, the above will only work in THUMB mode. For 32-bit ARM, you may have to use |
If you don't have access to unified syntax, the above will only work in THUMB mode. For 32-bit ARM, you may have to use |
||
< |
<syntaxhighlight lang="arm assembly">STMFD sp!,{r0-r12,lr} |
||
LDMFD sp!,{r0-r12,pc}</ |
LDMFD sp!,{r0-r12,pc}</syntaxhighlight> |
||
=={{header|Arturo}}== |
=={{header|Arturo}}== |
||
Line 282: | Line 282: | ||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
< |
<syntaxhighlight lang="ahk">; Define a function. |
||
function() |
function() |
||
{ |
{ |
||
Line 318: | Line 318: | ||
Suspended |
Suspended |
||
*/</ |
*/</syntaxhighlight> |
||
=={{header|BASIC}}== |
=={{header|BASIC}}== |
||
< |
<syntaxhighlight lang="basic">10 GOTO 100: REM jump to a specific line |
||
20 RUN 200: REM start the program running from a specific line</ |
20 RUN 200: REM start the program running from a specific line</syntaxhighlight> |
||
Some versions of basic allow line labels to be used. Here we jump to a label: |
Some versions of basic allow line labels to be used. Here we jump to a label: |
||
{{works with|BaCon}} |
{{works with|BaCon}} |
||
{{works with|QuickBASIC}} |
{{works with|QuickBASIC}} |
||
<lang |
<syntaxhighlight lang="qbasic">GOTO mylabel</syntaxhighlight> |
||
==={{header|Applesoft BASIC}}=== |
==={{header|Applesoft BASIC}}=== |
||
caveat: http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html |
caveat: http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html |
||
< |
<syntaxhighlight lang="applesoftbasic"> 0 REM GOTO |
||
100 GOTO 110 : REM JUMP TO A SPECIFIC LINE |
100 GOTO 110 : REM JUMP TO A SPECIFIC LINE |
||
110 RUN 120 : REM START THE PROGRAM RUNNING FROM A SPECIFIC LINE |
110 RUN 120 : REM START THE PROGRAM RUNNING FROM A SPECIFIC LINE |
||
Line 351: | Line 351: | ||
280 STOP : REM BREAK THE PROGRAM |
280 STOP : REM BREAK THE PROGRAM |
||
290 END : REM END THE PROGRAM |
290 END : REM END THE PROGRAM |
||
300 GOTO : REM NO LINE NUMBER, JUMPS TO LINE 0</ |
300 GOTO : REM NO LINE NUMBER, JUMPS TO LINE 0</syntaxhighlight> |
||
< |
<syntaxhighlight lang="applesoftbasic">CONT : REM CONTINUE, JUMP BACK TO WHERE THE PROGRAM STOPPED</syntaxhighlight> |
||
==={{header|IS-BASIC}}=== |
==={{header|IS-BASIC}}=== |
||
< |
<syntaxhighlight lang="is-basic">10 GOTO 100 ! jump to a specific line |
||
20 RUN 200 ! start the program running from a specific line</ |
20 RUN 200 ! start the program running from a specific line</syntaxhighlight> |
||
==={{header|Run BASIC}}=== |
==={{header|Run BASIC}}=== |
||
< |
<syntaxhighlight lang="runbasic">for i = 1 to 10 |
||
if i = 5 then goto [label5] |
if i = 5 then goto [label5] |
||
next i |
next i |
||
Line 378: | Line 378: | ||
[finish] |
[finish] |
||
print "done"</ |
print "done"</syntaxhighlight> |
||
=={{header|BASIC256}}== |
=={{header|BASIC256}}== |
||
Line 384: | Line 384: | ||
{{works with|QBasic}} |
{{works with|QBasic}} |
||
{{works with|Yabasic}} |
{{works with|Yabasic}} |
||
< |
<syntaxhighlight lang="freebasic">print "First line." |
||
gosub sub1 |
gosub sub1 |
||
print "Fifth line." |
print "Fifth line." |
||
Line 405: | Line 405: | ||
Finished: |
Finished: |
||
print "... with goto and gosub, thankfully." |
print "... with goto and gosub, thankfully." |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Igual que la entrada de FutureBasic.</pre> |
<pre>Igual que la entrada de FutureBasic.</pre> |
||
Line 411: | Line 411: | ||
=={{header|C}}== |
=={{header|C}}== |
||
C has <code>goto LABEL</code> keyword. |
C has <code>goto LABEL</code> keyword. |
||
< |
<syntaxhighlight lang="c"> if (x > 0) goto positive; |
||
else goto negative; |
else goto negative; |
||
Line 421: | Line 421: | ||
both: |
both: |
||
...</ |
...</syntaxhighlight> |
||
The label must be literal, not computed at run time. This won't work: |
The label must be literal, not computed at run time. This won't work: |
||
< |
<syntaxhighlight lang="c">goto (x > 0 ? positive : negative);</syntaxhighlight> |
||
<!-- Except if you're using GCC extensions, when you can do something that's very similar to that. Scary stuff! --> |
<!-- Except if you're using GCC extensions, when you can do something that's very similar to that. Scary stuff! --> |
||
You can <code>goto</code> ''almost'' anywhere inside the same function, but can't go across function boundaries. It's sometimes used to break out of nested loops:< |
You can <code>goto</code> ''almost'' anywhere inside the same function, but can't go across function boundaries. It's sometimes used to break out of nested loops:<syntaxhighlight lang="c">for (i = 0; ...) { |
||
for (j = 0; ...) { |
for (j = 0; ...) { |
||
if (condition_met) goto finish; |
if (condition_met) goto finish; |
||
} |
} |
||
}</ |
}</syntaxhighlight>although you can (not that you ''should'') jump into a loop, too:<syntaxhighlight lang="c"> goto danger; |
||
for (i = 0; i < 10; i++) { |
for (i = 0; i < 10; i++) { |
||
danger: /* unless you jumped here with i set to a proper value */ |
danger: /* unless you jumped here with i set to a proper value */ |
||
printf("%d\n", i); |
printf("%d\n", i); |
||
}</ |
}</syntaxhighlight> |
||
For unwrapping call stack and go back up to a caller, see [[Exceptions#C|longjmp example]]; more powerful, but more expensive and complicated, is POSIX [[Exceptions/Catch an exception thrown in a nested call#C|ucontext]]. |
For unwrapping call stack and go back up to a caller, see [[Exceptions#C|longjmp example]]; more powerful, but more expensive and complicated, is POSIX [[Exceptions/Catch an exception thrown in a nested call#C|ucontext]]. |
||
The best application for goto is error handling, this simplifies the resource clean up of a large function. |
The best application for goto is error handling, this simplifies the resource clean up of a large function. |
||
Line 440: | Line 440: | ||
<syntaxhighlight lang="c"> |
|||
<lang c> |
|||
char *str; |
char *str; |
||
int *array; |
int *array; |
||
Line 466: | Line 466: | ||
...// read in the csv file and convert to integers |
...// read in the csv file and convert to integers |
||
</syntaxhighlight> |
|||
</lang> |
|||
<syntaxhighlight lang="c"> |
|||
<lang c> |
|||
char *str; |
char *str; |
||
int *array; |
int *array; |
||
Line 495: | Line 495: | ||
exit: |
exit: |
||
return; |
return; |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
Like C, C# also has a <code>goto LABEL</code> keyword. This section is partly copied from the section on C, since both languages share common syntax. |
Like C, C# also has a <code>goto LABEL</code> keyword. This section is partly copied from the section on C, since both languages share common syntax. |
||
< |
<syntaxhighlight lang="csharp">if (x > 0) goto positive; |
||
else goto negative; |
else goto negative; |
||
Line 509: | Line 509: | ||
both: |
both: |
||
...</ |
...</syntaxhighlight> |
||
The label must be literal, not computed at run time. This won't work: |
The label must be literal, not computed at run time. This won't work: |
||
< |
<syntaxhighlight lang="csharp">goto (x > 0 ? positive : negative);</syntaxhighlight> |
||
You can <code>goto</code> ''almost'' anywhere inside the same method, but can't go across method boundaries. It's sometimes used to break out of nested loops: |
You can <code>goto</code> ''almost'' anywhere inside the same method, but can't go across method boundaries. It's sometimes used to break out of nested loops: |
||
< |
<syntaxhighlight lang="csharp">for (i = 0; ...) { |
||
for (j = 0; ...) { |
for (j = 0; ...) { |
||
if (condition_met) goto finish; |
if (condition_met) goto finish; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
The label must be in scope, so you cannot jump into a loop. This will not compile: |
The label must be in scope, so you cannot jump into a loop. This will not compile: |
||
< |
<syntaxhighlight lang="csharp">goto danger; |
||
for (i = 0; i < 10; i++) { |
for (i = 0; i < 10; i++) { |
||
danger: |
danger: |
||
Console.WriteLine(i); |
Console.WriteLine(i); |
||
}</ |
}</syntaxhighlight> |
||
In C#, you can also <code>goto</code> a label from within any section of a try .. catch block. However, it is not permitted to jump out of a finally block. |
In C#, you can also <code>goto</code> a label from within any section of a try .. catch block. However, it is not permitted to jump out of a finally block. |
||
< |
<syntaxhighlight lang="csharp">int i = 0; |
||
tryAgain: |
tryAgain: |
||
try { |
try { |
||
Line 538: | Line 538: | ||
finally { |
finally { |
||
//goto end; //Error |
//goto end; //Error |
||
}</ |
}</syntaxhighlight> |
||
Another usage of <code>goto</code> is to jump between <code>case</code> labels inside a <code>switch</code> statement: |
Another usage of <code>goto</code> is to jump between <code>case</code> labels inside a <code>switch</code> statement: |
||
< |
<syntaxhighlight lang="csharp">public int M(int n) { |
||
int result = 0; |
int result = 0; |
||
switch (n) { |
switch (n) { |
||
Line 555: | Line 555: | ||
} |
} |
||
return result; |
return result; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|C++}}== |
=={{header|C++}}== |
||
Like C, C++ also has a <code>goto LABEL</code> statement which can be used to jump within a function. |
Like C, C++ also has a <code>goto LABEL</code> statement which can be used to jump within a function. |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
#include <utility> |
#include <utility> |
||
Line 605: | Line 605: | ||
cout << "k = " << k << "\n"; // k was never initialized, accessing it is undefined behavior |
cout << "k = " << k << "\n"; // k was never initialized, accessing it is undefined behavior |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 619: | Line 619: | ||
=={{header|COBOL}}== |
=={{header|COBOL}}== |
||
< |
<syntaxhighlight lang="cobol">IDENTIFICATION DIVISION. |
||
PROGRAM-ID. JUMPS-PROGRAM. |
PROGRAM-ID. JUMPS-PROGRAM. |
||
* Nobody writes like this, of course; but... |
* Nobody writes like this, of course; but... |
||
Line 642: | Line 642: | ||
AN-ARBITRARY-PARAGRAPH. |
AN-ARBITRARY-PARAGRAPH. |
||
DISPLAY 'Edsger who now?' |
DISPLAY 'Edsger who now?' |
||
GO TO SOME-OTHER-PARAGRAPH.</ |
GO TO SOME-OTHER-PARAGRAPH.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Edsger who now? |
<pre>Edsger who now? |
||
Line 649: | Line 649: | ||
'''COBOL''' also supports computed go to phrases, given a list of labels (paragraph names) and an integer index into that list. |
'''COBOL''' also supports computed go to phrases, given a list of labels (paragraph names) and an integer index into that list. |
||
< |
<syntaxhighlight lang="cobol">01 province pic 99 value 2. |
||
GO TO quebec, ontario, manitoba DEPENDING ON province</ |
GO TO quebec, ontario, manitoba DEPENDING ON province</syntaxhighlight> |
||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
In Common Lisp you can jump anywhere inside a tagbody. |
In Common Lisp you can jump anywhere inside a tagbody. |
||
< |
<syntaxhighlight lang="lisp"> |
||
(tagbody |
(tagbody |
||
beginning |
beginning |
||
Line 668: | Line 668: | ||
(sleep 1) |
(sleep 1) |
||
(go middle)) |
(go middle)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 683: | Line 683: | ||
=={{header|Computer/zero Assembly}}== |
=={{header|Computer/zero Assembly}}== |
||
A <tt>JMP</tt> (jump) instruction can transfer control to any point in memory. Its target can be modified at run time, if required, by using instruction arithmetic: |
A <tt>JMP</tt> (jump) instruction can transfer control to any point in memory. Its target can be modified at run time, if required, by using instruction arithmetic: |
||
< |
<syntaxhighlight lang="czasm"> LDA goto |
||
SUB somewhere |
SUB somewhere |
||
ADD somewhereElse |
ADD somewhereElse |
||
STA goto |
STA goto |
||
goto: JMP somewhere</ |
goto: JMP somewhere</syntaxhighlight> |
||
By the time execution reaches the instruction labelled <tt>goto</tt>, that instruction has become <tt>JMP somewhereElse</tt>. (This kind of coding does not, however, necessarily make the flow of control easier to follow.) |
By the time execution reaches the instruction labelled <tt>goto</tt>, that instruction has become <tt>JMP somewhereElse</tt>. (This kind of coding does not, however, necessarily make the flow of control easier to follow.) |
||
Line 694: | Line 694: | ||
=={{header|DCL}}== |
=={{header|DCL}}== |
||
< |
<syntaxhighlight lang="dcl">$ return ! ignored since we haven't done a gosub yet |
||
$ |
$ |
||
$ if p1 .eqs. "" then $ goto main |
$ if p1 .eqs. "" then $ goto main |
||
Line 764: | Line 764: | ||
$ sub4: subroutine |
$ sub4: subroutine |
||
$ exit |
$ exit |
||
$ endsubroutine</ |
$ endsubroutine</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>$ @jump_anywhere |
<pre>$ @jump_anywhere |
||
Line 865: | Line 865: | ||
Déjà Vu supports continuations: |
Déjà Vu supports continuations: |
||
< |
<syntaxhighlight lang="dejavu">example: |
||
!print "First part" |
!print "First part" |
||
yield |
yield |
||
Line 872: | Line 872: | ||
local :continue example |
local :continue example |
||
!print "Interrupted" |
!print "Interrupted" |
||
continue</ |
continue</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>First part |
<pre>First part |
||
Line 883: | Line 883: | ||
Every function/procedure must have your own labels, globals labels won't work in local functions. |
Every function/procedure must have your own labels, globals labels won't work in local functions. |
||
The label must be literal, not computed at run time. |
The label must be literal, not computed at run time. |
||
<syntaxhighlight lang="delphi"> |
|||
<lang Delphi> |
|||
var |
var |
||
x: Integer = 5; |
x: Integer = 5; |
||
Line 905: | Line 905: | ||
readln; |
readln; |
||
end. |
end. |
||
</syntaxhighlight> |
|||
</lang> |
|||
Although you can (not that you should) jump into a loop, too. If you use a loop variable, it will start with its value. |
Although you can (not that you should) jump into a loop, too. If you use a loop variable, it will start with its value. |
||
If the loop variable has a value out range loop limits, then you cause a intinity loop. |
If the loop variable has a value out range loop limits, then you cause a intinity loop. |
||
<syntaxhighlight lang="delphi"> |
|||
<lang Delphi> |
|||
label |
label |
||
inloop, outloop; |
inloop, outloop; |
||
Line 927: | Line 927: | ||
readln; |
readln; |
||
end. |
end. |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 942: | Line 942: | ||
This won't work. |
This won't work. |
||
<syntaxhighlight lang="delphi"> |
|||
<lang Delphi> |
|||
label |
label |
||
tryAgain, finished; |
tryAgain, finished; |
||
Line 960: | Line 960: | ||
readln; |
readln; |
||
end. |
end. |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
Jumps are limited to [[Exceptions]]. |
Jumps are limited to [[Exceptions]]. |
||
Line 966: | Line 966: | ||
=={{header|ERRE}}== |
=={{header|ERRE}}== |
||
ERRE has a GOTO statement in the form GOTO <label>. <label> is a numercic string and must be declared. ERRE GOTO is local only: you can jump only within the same procedure or within the main program. In the following example there are two errors: |
ERRE has a GOTO statement in the form GOTO <label>. <label> is a numercic string and must be declared. ERRE GOTO is local only: you can jump only within the same procedure or within the main program. In the following example there are two errors: |
||
<lang> |
<syntaxhighlight lang="text"> |
||
PROGRAM GOTO_ERR |
PROGRAM GOTO_ERR |
||
Line 986: | Line 986: | ||
IF J<>0 THEN GOTO 100 END IF |
IF J<>0 THEN GOTO 100 END IF |
||
END PROGRAM |
END PROGRAM |
||
</syntaxhighlight> |
|||
</lang> |
|||
You can't jump from procedure P1 to procedure P2 or from main to procedure P2 (label 99). Jump to label 100 is allowed (within main program). |
You can't jump from procedure P1 to procedure P2 or from main to procedure P2 (label 99). Jump to label 100 is allowed (within main program). |
||
Line 996: | Line 996: | ||
A continuation is conceptually simple in Factor. It is a tuple consisting of slots for the five stacks that make up the entire execution context: data stack, call stack, retain stack, name stack, and catch stack. To create a continuation from the current execution context, use <code>current-continuation</code>. |
A continuation is conceptually simple in Factor. It is a tuple consisting of slots for the five stacks that make up the entire execution context: data stack, call stack, retain stack, name stack, and catch stack. To create a continuation from the current execution context, use <code>current-continuation</code>. |
||
< |
<syntaxhighlight lang="factor">USING: continuations prettyprint ; |
||
current-continuation short.</ |
current-continuation short.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,006: | Line 1,006: | ||
Following is a simple example where we reify a continuation before attempting to divide 1 by 0. Note the current execution context (a <code>continuation</code> object) is placed on the top of the data stack inside the <code>callcc0</code> quotation which <code>continue</code> then reifies. |
Following is a simple example where we reify a continuation before attempting to divide 1 by 0. Note the current execution context (a <code>continuation</code> object) is placed on the top of the data stack inside the <code>callcc0</code> quotation which <code>continue</code> then reifies. |
||
< |
<syntaxhighlight lang="factor">USING: continuations math prettyprint ; |
||
[ 10 2 / . continue 1 0 / . ] callcc0</ |
[ 10 2 / . continue 1 0 / . ] callcc0</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,015: | Line 1,015: | ||
We can even reify a continuation while taking an object back with us. |
We can even reify a continuation while taking an object back with us. |
||
< |
<syntaxhighlight lang="factor">USING: continuations kernel math ; |
||
[ 10 2 / swap continue-with 1 0 / ] callcc1</ |
[ 10 2 / swap continue-with 1 0 / ] callcc1</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,053: | Line 1,053: | ||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
< |
<syntaxhighlight lang="forth">\ this prints five lines containing elements from the two |
||
\ words 'proc1' and 'proc2'. gotos are used here to jump |
\ words 'proc1' and 'proc2'. gotos are used here to jump |
||
\ into and out of the two words at various points, as well |
\ into and out of the two words at various points, as well |
||
Line 1,081: | Line 1,081: | ||
5 1 proc2 |
5 1 proc2 |
||
bye</ |
bye</syntaxhighlight> |
||
Output: |
Output: |
||
< |
<syntaxhighlight lang="forth">line 1 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
||
line 2 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
line 2 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
||
line 3 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
line 3 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
||
line 4 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
line 4 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
||
line 5 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5</ |
line 5 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5</syntaxhighlight> |
||
< |
<syntaxhighlight lang="forth">\ this is congruent to the previous demonstration, employing |
||
\ a data structure to store goto/jump addresses instead of |
\ a data structure to store goto/jump addresses instead of |
||
\ separate variables, and two additional words 'mark_goto' and |
\ separate variables, and two additional words 'mark_goto' and |
||
Line 1,120: | Line 1,120: | ||
: go 5 1 6 goto ; go |
: go 5 1 6 goto ; go |
||
bye</ |
bye</syntaxhighlight> |
||
Output: |
Output: |
||
< |
<syntaxhighlight lang="forth">line 1 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
||
line 2 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
line 2 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
||
line 3 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
line 3 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
||
line 4 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
line 4 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5 |
||
line 5 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5</ |
line 5 --> item6 item1 item7 item2 item8 item3 item9 item4 item10 item5</syntaxhighlight> |
||
< |
<syntaxhighlight lang="forth">\ works with ficl, pfe, gforth, bigforth, and vfx. |
||
\ swiftforth may crash, iforth does not function. |
\ swiftforth may crash, iforth does not function. |
||
Line 1,167: | Line 1,167: | ||
5 1 go |
5 1 go |
||
bye</ |
bye</syntaxhighlight> |
||
Output: |
Output: |
||
< |
<syntaxhighlight lang="forth">iteration 1 --> goto1 goto3 goto5 goto7 goto9 goto2 goto4 goto6 goto8 |
||
iteration 2 --> goto1 goto3 goto5 goto7 goto9 goto2 goto4 goto6 goto8 |
iteration 2 --> goto1 goto3 goto5 goto7 goto9 goto2 goto4 goto6 goto8 |
||
iteration 3 --> goto1 goto3 goto5 goto7 goto9 goto2 goto4 goto6 goto8 |
iteration 3 --> goto1 goto3 goto5 goto7 goto9 goto2 goto4 goto6 goto8 |
||
iteration 4 --> goto1 goto3 goto5 goto7 goto9 goto2 goto4 goto6 goto8 |
iteration 4 --> goto1 goto3 goto5 goto7 goto9 goto2 goto4 goto6 goto8 |
||
iteration 5 --> goto1 goto3 goto5 goto7 goto9 goto2 goto4 goto6 goto8</ |
iteration 5 --> goto1 goto3 goto5 goto7 goto9 goto2 goto4 goto6 goto8</syntaxhighlight> |
||
Line 1,180: | Line 1,180: | ||
Although Forth was designed to be a structured programming language it is simple to add a generic jump anywhere. |
Although Forth was designed to be a structured programming language it is simple to add a generic jump anywhere. |
||
The Forth dictionary of WORDs is essentially a linked list of labels. We can find the execution token for any label in the dictionary with the ['] operator and jump to it with the keyword EXECUTE. |
The Forth dictionary of WORDs is essentially a linked list of labels. We can find the execution token for any label in the dictionary with the ['] operator and jump to it with the keyword EXECUTE. |
||
< |
<syntaxhighlight lang="forth">: GOTO ['] EXECUTE ;</syntaxhighlight> |
||
TEST |
TEST |
||
< |
<syntaxhighlight lang="forth">: WORLD ." World!" ; |
||
: HELLO ." Hello" ; |
: HELLO ." Hello" ; |
||
GOTO CR GOTO HELLO GOTO SPACE GOTO WORLD |
GOTO CR GOTO HELLO GOTO SPACE GOTO WORLD |
||
Hello World!</ |
Hello World!</syntaxhighlight> |
||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
Line 1,229: | Line 1,229: | ||
The following program demonstrate the use of the various 'Goto' constructs in the -lang fb dialect only: |
The following program demonstrate the use of the various 'Goto' constructs in the -lang fb dialect only: |
||
< |
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64 |
||
' compiled with -lang fb (the default) and -e switches |
' compiled with -lang fb (the default) and -e switches |
||
Line 1,278: | Line 1,278: | ||
Print |
Print |
||
Print "Pres any key to quit" |
Print "Pres any key to quit" |
||
Print</ |
Print</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,297: | Line 1,297: | ||
All that said, don't use spaghetti code -- use functions. You can still by spark plugs for a 1985 Yugo, but why? |
All that said, don't use spaghetti code -- use functions. You can still by spark plugs for a 1985 Yugo, but why? |
||
< |
<syntaxhighlight lang="futurebasic"> |
||
include "ConsoleWindow" |
include "ConsoleWindow" |
||
Line 1,318: | Line 1,318: | ||
print "... with goto and gosub, thankfully." |
print "... with goto and gosub, thankfully." |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 1,336: | Line 1,336: | ||
For example: |
For example: |
||
< |
<syntaxhighlight lang="go">package main |
||
import "fmt" |
import "fmt" |
||
Line 1,356: | Line 1,356: | ||
k++ |
k++ |
||
fmt.Println(k) |
fmt.Println(k) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,372: | Line 1,372: | ||
4 |
4 |
||
</pre> |
</pre> |
||
::< |
::<syntaxhighlight lang="go">package main |
||
import "fmt" |
import "fmt" |
||
Line 1,406: | Line 1,406: | ||
func init() { |
func init() { |
||
fmt.Println("run first") |
fmt.Println("run first") |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Harbour}}== |
=={{header|Harbour}}== |
||
Line 1,417: | Line 1,417: | ||
First some boilerplate, where we define labels and goto "operator". |
First some boilerplate, where we define labels and goto "operator". |
||
< |
<syntaxhighlight lang="haskell">import Control.Monad.Cont |
||
data LabelT r m = LabelT (ContT r m ()) |
data LabelT r m = LabelT (ContT r m ()) |
||
Line 1,429: | Line 1,429: | ||
runProgram :: Monad m => ContT r m r -> m r |
runProgram :: Monad m => ContT r m r -> m r |
||
runProgram program = runContT program return</ |
runProgram program = runContT program return</syntaxhighlight> |
||
Here is example of using labels in IO: |
Here is example of using labels in IO: |
||
< |
<syntaxhighlight lang="haskell">main = runProgram $ |
||
do |
do |
||
start <- label |
start <- label |
||
Line 1,440: | Line 1,440: | ||
then do lift $ putStrLn "Name can't be empty!" |
then do lift $ putStrLn "Name can't be empty!" |
||
goto start |
goto start |
||
else lift $ putStrLn ("Hello, " ++ name)</ |
else lift $ putStrLn ("Hello, " ++ name)</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
Line 1,452: | Line 1,452: | ||
We can build tiny EDSL to get rid of explicit lifting and to add refferences: |
We can build tiny EDSL to get rid of explicit lifting and to add refferences: |
||
< |
<syntaxhighlight lang="haskell">import Data.IORef |
||
readInt = lift $ readLn >>= newIORef |
readInt = lift $ readLn >>= newIORef |
||
get ref = lift $ readIORef ref |
get ref = lift $ readIORef ref |
||
set ref expr = lift $ modifyIORef ref (const expr) |
set ref expr = lift $ modifyIORef ref (const expr) |
||
output expr = lift $ putStrLn expr</ |
output expr = lift $ putStrLn expr</syntaxhighlight> |
||
and implement famous Euclid's algorithm as an imperative program: |
and implement famous Euclid's algorithm as an imperative program: |
||
< |
<syntaxhighlight lang="haskell">gcdProg = runProgram $ callCC $ \exit -> -- <--------+ |
||
do -- | |
do -- | |
||
start <- label -- <-----+ | |
start <- label -- <-----+ | |
||
Line 1,478: | Line 1,478: | ||
when (n > m) $ set nr (n - m) -- | |
when (n > m) $ set nr (n - m) -- | |
||
when (m > n) $ set mr (m - n) -- | |
when (m > n) $ set mr (m - n) -- | |
||
goto loop -- ---+</ |
goto loop -- ---+</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
Line 1,492: | Line 1,492: | ||
In native Haskell such flow jumps are done by function calls: |
In native Haskell such flow jumps are done by function calls: |
||
< |
<syntaxhighlight lang="haskell">gcdFProg = start |
||
where |
where |
||
start = do |
start = do |
||
Line 1,508: | Line 1,508: | ||
| n == m = n |
| n == m = n |
||
| n < m = loop n (m-n) |
| n < m = loop n (m-n) |
||
| n > m = loop (n-m) m</ |
| n > m = loop (n-m) m</syntaxhighlight> |
||
Or without explicit recursion and branching: |
Or without explicit recursion and branching: |
||
< |
<syntaxhighlight lang="haskell">import Control.Applicative |
||
import Control.Monad.Trans.Maybe |
import Control.Monad.Trans.Maybe |
||
Line 1,523: | Line 1,523: | ||
process = gcd <$> (lift readLn >>= exitOn 0) <*> lift readLn |
process = gcd <$> (lift readLn >>= exitOn 0) <*> lift readLn |
||
exitOn n x = if x == n then empty else pure x</ |
exitOn n x = if x == n then empty else pure x</syntaxhighlight> |
||
=={{header|i}}== |
=={{header|i}}== |
||
< |
<syntaxhighlight lang="i">//'i' does not have goto statements, instead control flow is the only legal way to navigate the program. |
||
concept there() { |
concept there() { |
||
print("Hello there") |
print("Hello there") |
||
Line 1,554: | Line 1,554: | ||
//Move to the code contained in the 'there' function. |
//Move to the code contained in the 'there' function. |
||
there() |
there() |
||
}</ |
}</syntaxhighlight> |
||
=={{header|J}}== |
=={{header|J}}== |
||
Line 1,560: | Line 1,560: | ||
For example: |
For example: |
||
< |
<syntaxhighlight lang="j">F=: verb define |
||
smoutput 'Now we are in F' |
smoutput 'Now we are in F' |
||
G'' |
G'' |
||
Line 1,573: | Line 1,573: | ||
F'' |
F'' |
||
Now we are in F |
Now we are in F |
||
Now we are in G</ |
Now we are in G</syntaxhighlight> |
||
J also supports jumps to labels within a definition: |
J also supports jumps to labels within a definition: |
||
< |
<syntaxhighlight lang="j">H=: verb define |
||
smoutput 'a' |
smoutput 'a' |
||
label_b. |
label_b. |
||
Line 1,594: | Line 1,594: | ||
c |
c |
||
g |
g |
||
e</ |
e</syntaxhighlight> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
The closest thing that Java has to a "goto" is labelled loops: |
The closest thing that Java has to a "goto" is labelled loops: |
||
< |
<syntaxhighlight lang="java">loop1: while (x != 0) { |
||
loop2: for (int i = 0; i < 10; i++) { |
loop2: for (int i = 0; i < 10; i++) { |
||
loop3: do { |
loop3: do { |
||
Line 1,615: | Line 1,615: | ||
} |
} |
||
//loop1 calculations executed after loop2 is done or if the break is executed, skipped if the continue is executed |
//loop1 calculations executed after loop2 is done or if the break is executed, skipped if the continue is executed |
||
}</ |
}</syntaxhighlight> |
||
It's frowned upon to use exceptions for non-exceptional paths, so get ready to frown at this fizz-buzz player that makes use of <tt>try/catch/finally</tt> to jump to the right places for printing: |
It's frowned upon to use exceptions for non-exceptional paths, so get ready to frown at this fizz-buzz player that makes use of <tt>try/catch/finally</tt> to jump to the right places for printing: |
||
< |
<syntaxhighlight lang="java"> |
||
public class FizzBuzzThrower { |
public class FizzBuzzThrower { |
||
public static void main( String [] args ) { |
public static void main( String [] args ) { |
||
Line 1,636: | Line 1,636: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|jq}}== |
=={{header|jq}}== |
||
Line 1,644: | Line 1,644: | ||
jq supports named labels ("label $NAME") and break statements ("break $NAME"). Usage |
jq supports named labels ("label $NAME") and break statements ("break $NAME"). Usage |
||
follows the pattern: |
follows the pattern: |
||
< |
<syntaxhighlight lang="jq">label $out | ... break $out ...</syntaxhighlight> |
||
When, during program execution, a "break" statement is encountered, the program |
When, during program execution, a "break" statement is encountered, the program |
||
Line 1,655: | Line 1,655: | ||
Break statements are used to interrupt a generator. For example, to emit |
Break statements are used to interrupt a generator. For example, to emit |
||
the least positive integer satisfying sin(1/N) == (1/N) using IEEE 64-bit arithmetic: |
the least positive integer satisfying sin(1/N) == (1/N) using IEEE 64-bit arithmetic: |
||
< |
<syntaxhighlight lang="jq">label $out | 1e7 | while(true; .+1) | if (1/.) | . == sin then (., break $out) else empty end</syntaxhighlight> |
||
Here, the "while" filter is an unbounded generator. The answer is 46530688. |
Here, the "while" filter is an unbounded generator. The answer is 46530688. |
||
Line 1,663: | Line 1,663: | ||
Indeed, a better way to solve the type of problem mentioned above is by using one of the jq-provided control structures. |
Indeed, a better way to solve the type of problem mentioned above is by using one of the jq-provided control structures. |
||
For example, the above problem can be solved more succinctly and transparently using until/2: |
For example, the above problem can be solved more succinctly and transparently using until/2: |
||
< |
<syntaxhighlight lang="jq">1e7 | until(1/. | . == sin; .+1)</syntaxhighlight> |
||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
Julia provides the @goto and @label macros for goto within functions but these cannot be used at the global level or to jump from one function to another. The macros can however be used for a typical use of @goto -- jumping out to a specific level from nested loops within a function. |
Julia provides the @goto and @label macros for goto within functions but these cannot be used at the global level or to jump from one function to another. The macros can however be used for a typical use of @goto -- jumping out to a specific level from nested loops within a function. |
||
< |
<syntaxhighlight lang="julia"> |
||
function example() |
function example() |
||
println("Hello ") |
println("Hello ") |
||
Line 1,676: | Line 1,676: | ||
println("world") |
println("world") |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
Line 1,684: | Line 1,684: | ||
For example: |
For example: |
||
< |
<syntaxhighlight lang="scala">// version 1.0.6 |
||
fun main(args: Array<String>) { |
fun main(args: Array<String>) { |
||
Line 1,699: | Line 1,699: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,723: | Line 1,723: | ||
* Lingo supports "unwinding the call stack" via the abort command that exits the current call stack: |
* Lingo supports "unwinding the call stack" via the abort command that exits the current call stack: |
||
< |
<syntaxhighlight lang="lingo">on foo |
||
abort() |
abort() |
||
end |
end |
||
Line 1,730: | Line 1,730: | ||
foo() |
foo() |
||
put "This will never be printed" |
put "This will never be printed" |
||
end</ |
end</syntaxhighlight> |
||
* Rarely used, but Lingo supports saving a continuation via the play ... play done construct: |
* Rarely used, but Lingo supports saving a continuation via the play ... play done construct: |
||
< |
<syntaxhighlight lang="lingo">on testPlayDone () |
||
-- Start some asynchronous process (like e.g. a HTTP request). |
-- Start some asynchronous process (like e.g. a HTTP request). |
||
Line 1,744: | Line 1,744: | ||
-- The following will be executed only after 'play done' was called in the asynchronous process code |
-- The following will be executed only after 'play done' was called in the asynchronous process code |
||
put "Done. The asynchronous process returned the result:" && _global.result |
put "Done. The asynchronous process returned the result:" && _global.result |
||
end</ |
end</syntaxhighlight> |
||
=={{header|Logtalk}}== |
=={{header|Logtalk}}== |
||
Line 1,751: | Line 1,751: | ||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
Lua 5.2 introduced a <code>goto</code> statement along with labels. It was somewhat controversially implemented instead of a <code>continue</code> keyword, but it is more flexible and supports other types of jumps as well. <code>goto</code> only supports statically-defined labels. |
Lua 5.2 introduced a <code>goto</code> statement along with labels. It was somewhat controversially implemented instead of a <code>continue</code> keyword, but it is more flexible and supports other types of jumps as well. <code>goto</code> only supports statically-defined labels. |
||
< |
<syntaxhighlight lang="lua">-- Forward jump |
||
goto skip_print |
goto skip_print |
||
print "won't print" |
print "won't print" |
||
Line 1,788: | Line 1,788: | ||
end |
end |
||
print "not found" |
print "not found" |
||
::exit::</ |
::exit::</syntaxhighlight> |
||
=={{header|M2000 Interpreter}}== |
=={{header|M2000 Interpreter}}== |
||
Line 1,797: | Line 1,797: | ||
After Else and Then we can place number to jump (same as Goto number). Goto can't take variable. We can use On Goto to use an expression to choose label (we can place numbers or named labels) |
After Else and Then we can place number to jump (same as Goto number). Goto can't take variable. We can use On Goto to use an expression to choose label (we can place numbers or named labels) |
||
===Using GOTO and GOSUB=== |
===Using GOTO and GOSUB=== |
||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module Checkit { |
Module Checkit { |
||
Module Alfa { |
Module Alfa { |
||
Line 1,831: | Line 1,831: | ||
} |
} |
||
Checkit |
Checkit |
||
</syntaxhighlight> |
|||
</lang> |
|||
===Simulate Run Basic Entry=== |
===Simulate Run Basic Entry=== |
||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module LikeRunBasic { |
Module LikeRunBasic { |
||
for i = 1 to 10 |
for i = 1 to 10 |
||
Line 1,858: | Line 1,858: | ||
} |
} |
||
LikeRunBasic |
LikeRunBasic |
||
</syntaxhighlight> |
|||
</lang> |
|||
===Simulate Go Entry=== |
===Simulate Go Entry=== |
||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module LikeGo { |
Module LikeGo { |
||
\\ simulate Go for |
\\ simulate Go for |
||
Line 1,944: | Line 1,944: | ||
LikeGo_No_Labels |
LikeGo_No_Labels |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
Line 1,953: | Line 1,953: | ||
=={{header|MBS}}== |
=={{header|MBS}}== |
||
<lang |
<syntaxhighlight lang="mbs">goto mylabel;</syntaxhighlight> |
||
=={{header|МК-61/52}}== |
=={{header|МК-61/52}}== |
||
<lang>БП XX</ |
<syntaxhighlight lang="text">БП XX</syntaxhighlight> |
||
'''XX''' is any address. |
'''XX''' is any address. |
||
Line 1,972: | Line 1,972: | ||
Most of the time you won't be jumping to a specific address. You can place a label before any instruction, and a jump to that label is the same as a jump to the address of that instruction. |
Most of the time you won't be jumping to a specific address. You can place a label before any instruction, and a jump to that label is the same as a jump to the address of that instruction. |
||
< |
<syntaxhighlight lang="mips"> |
||
j GoHere ;the assembler will convert this label to a constant memory address for us. |
j GoHere ;the assembler will convert this label to a constant memory address for us. |
||
Line 1,979: | Line 1,979: | ||
GoHere: |
GoHere: |
||
addiu $t0,1 ;this instruction is the first one executed after jumping.</ |
addiu $t0,1 ;this instruction is the first one executed after jumping.</syntaxhighlight> |
||
Line 1,989: | Line 1,989: | ||
Some interpreters will allow you jump between blocks of the same depth. Others will let you leave, but not enter, a block. |
Some interpreters will allow you jump between blocks of the same depth. Others will let you leave, but not enter, a block. |
||
< |
<syntaxhighlight lang="mumps"> ;Go to a label within the program file |
||
Goto Label |
Goto Label |
||
;Go to a line below a label |
;Go to a line below a label |
||
Line 2,005: | Line 2,005: | ||
. Goto Out |
. Goto Out |
||
Out Quit |
Out Quit |
||
Goto NoNo+2</ |
Goto NoNo+2</syntaxhighlight> |
||
=={{header|Neko}}== |
=={{header|Neko}}== |
||
Line 2,011: | Line 2,011: | ||
Neko supports colon terminated labels, and a builtin '''$goto(label)'''. This builtin is special in that the label argument is not dereferenced as a normal Neko expression, but specifically as a label. |
Neko supports colon terminated labels, and a builtin '''$goto(label)'''. This builtin is special in that the label argument is not dereferenced as a normal Neko expression, but specifically as a label. |
||
< |
<syntaxhighlight lang="actionscript">$print("start\n") |
||
$goto(skip) |
$goto(skip) |
||
$print("Jumped over") |
$print("Jumped over") |
||
skip: |
skip: |
||
$print("end\n")</ |
$print("end\n")</syntaxhighlight> |
||
The NekoVM keeps exception and call stacks in sync when jumping across boundaries to code blocks, but may not include some initiating side effects. For instance, jumping past a '''try''' phrase into the middle of the code block (where the try is not evaluated) will not catch the '''catch''' of the try catch pair. There are other cases where '''$goto()''' can cross semantic boundaries; a practice best avoided. |
The NekoVM keeps exception and call stacks in sync when jumping across boundaries to code blocks, but may not include some initiating side effects. For instance, jumping past a '''try''' phrase into the middle of the code block (where the try is not evaluated) will not catch the '''catch''' of the try catch pair. There are other cases where '''$goto()''' can cross semantic boundaries; a practice best avoided. |
||
Line 2,021: | Line 2,021: | ||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
Nim has exceptions and labelled breaks: |
Nim has exceptions and labelled breaks: |
||
< |
<syntaxhighlight lang="nim"> |
||
block outer: |
block outer: |
||
for i in 0..1000: |
for i in 0..1000: |
||
for j in 0..1000: |
for j in 0..1000: |
||
if i + j == 3: |
if i + j == 3: |
||
break outer</ |
break outer</syntaxhighlight> |
||
=={{header|Oforth}}== |
=={{header|Oforth}}== |
||
Line 2,038: | Line 2,038: | ||
Some portion of code can be restarted (as recursion) and skipped (as continuation). |
Some portion of code can be restarted (as recursion) and skipped (as continuation). |
||
< |
<syntaxhighlight lang="scheme"> |
||
; recursion: |
; recursion: |
||
(let loop ((n 10)) |
(let loop ((n 10)) |
||
Line 2,052: | Line 2,052: | ||
(print "ok.") |
(print "ok.") |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Line 2,061: | Line 2,061: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
Perl's <code>goto LABEL</code> and <code>goto EXPR</code> are a little too powerful to be safe. Use only under extreme duress (actually, not even then). <code>goto &SUB</code> is esoteric but much more innocuous and can occasionally be handy. |
Perl's <code>goto LABEL</code> and <code>goto EXPR</code> are a little too powerful to be safe. Use only under extreme duress (actually, not even then). <code>goto &SUB</code> is esoteric but much more innocuous and can occasionally be handy. |
||
< |
<syntaxhighlight lang="perl">sub outer { |
||
print "In outer, calling inner:\n"; |
print "In outer, calling inner:\n"; |
||
inner(); |
inner(); |
||
Line 2,095: | Line 2,095: | ||
print "\nCalling inner:\n"; |
print "\nCalling inner:\n"; |
||
inner(); # will die</ |
inner(); # will die</syntaxhighlight> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Line 2,101: | Line 2,101: | ||
Using this 'baroque' syntax is viewed as an effective means of dissuading novices from adopting goto as a weapon of choice. |
Using this 'baroque' syntax is viewed as an effective means of dissuading novices from adopting goto as a weapon of choice. |
||
Note that pwa/p2js does not support #ilASM{} at all. <!--(notonline)--> |
Note that pwa/p2js does not support #ilASM{} at all. <!--(notonline)--> |
||
< |
<syntaxhighlight lang="phix">#ilASM{ jmp :%somelabel } |
||
... |
... |
||
#ilASM{ :%somelabel }</ |
#ilASM{ :%somelabel }</syntaxhighlight> |
||
The above shows a global label, which can only be declared in top-level code, not inside a routine, and can be referenced from anywhere. |
The above shows a global label, which can only be declared in top-level code, not inside a routine, and can be referenced from anywhere. |
||
Local labels are declared with a double colon (::) and referenced with a single colon |
Local labels are declared with a double colon (::) and referenced with a single colon |
||
< |
<syntaxhighlight lang="phix">#ilASM{ jmp :local |
||
... |
... |
||
::local }</ |
::local }</syntaxhighlight> |
||
They can only be referenced at the top level from within the same #ilASM construct, or anywhere within the routine where they are defined. |
They can only be referenced at the top level from within the same #ilASM construct, or anywhere within the routine where they are defined. |
||
Phix also supports anonymous local labels |
Phix also supports anonymous local labels |
||
< |
<syntaxhighlight lang="phix">#ilASM{ jmp @f |
||
... |
... |
||
@@: |
@@: |
||
... |
... |
||
jle @b }</ |
jle @b }</syntaxhighlight> |
||
There are also optional (global) labels: |
There are also optional (global) labels: |
||
< |
<syntaxhighlight lang="phix">#ilASM{ call :!optlbl |
||
[32] |
[32] |
||
pop eax |
pop eax |
||
Line 2,131: | Line 2,131: | ||
push qword[rsp] |
push qword[rsp] |
||
[] |
[] |
||
ret }</ |
ret }</syntaxhighlight> |
||
These are obviously more useful when the reference and declaration are in separate files: if the file containing the declaration is not included, the reference quietly resolves to 0. |
These are obviously more useful when the reference and declaration are in separate files: if the file containing the declaration is not included, the reference quietly resolves to 0. |
||
The above code shows how to duplicate the return address and discard on return, so that execution carries on at the next instruction if the definition is not present. |
The above code shows how to duplicate the return address and discard on return, so that execution carries on at the next instruction if the definition is not present. |
||
Line 2,139: | Line 2,139: | ||
Lastly (for completeness) there are init labels, defined using |
Lastly (for completeness) there are init labels, defined using |
||
<lang |
<syntaxhighlight lang="phix">#ilASM{ :>init }</syntaxhighlight> |
||
These are used by the VM (eg builtins\VM\pStack.e declares :>initStack) to specify initialisation code which must be run at startup. They can also be called like a normal global label. |
These are used by the VM (eg builtins\VM\pStack.e declares :>initStack) to specify initialisation code which must be run at startup. They can also be called like a normal global label. |
||
Line 2,150: | Line 2,150: | ||
There is no 'go' or 'goto' function in PicoLisp, but it can be emulated with normal list processing functions. This allows "jumps" to arbitrary locations within (the same or other) functions. The following example implements a "loop": |
There is no 'go' or 'goto' function in PicoLisp, but it can be emulated with normal list processing functions. This allows "jumps" to arbitrary locations within (the same or other) functions. The following example implements a "loop": |
||
< |
<syntaxhighlight lang="picolisp">(de foo (N) |
||
(prinl "This is 'foo'") |
(prinl "This is 'foo'") |
||
(printsp N) |
(printsp N) |
||
(or (=0 (dec 'N)) (run (cddr foo))) )</ |
(or (=0 (dec 'N)) (run (cddr foo))) )</syntaxhighlight> |
||
Test: |
Test: |
||
<pre>: (foo 7) |
<pre>: (foo 7) |
||
Line 2,168: | Line 2,168: | ||
<br>In structured programming, the only place where a <code>goto</code> can be is inside <code>on</code> units to handle exceptions without recursion. |
<br>In structured programming, the only place where a <code>goto</code> can be is inside <code>on</code> units to handle exceptions without recursion. |
||
<lang |
<syntaxhighlight lang="pli">on conversion goto restart;</syntaxhighlight> |
||
=={{header|PL/SQL}}== |
=={{header|PL/SQL}}== |
||
PL/SQL supports both GOTOs and structured exception handling: |
PL/SQL supports both GOTOs and structured exception handling: |
||
< |
<syntaxhighlight lang="pl/sql">DECLARE |
||
i number := 5; |
i number := 5; |
||
divide_by_zero EXCEPTION; |
divide_by_zero EXCEPTION; |
||
Line 2,197: | Line 2,197: | ||
DBMS_OUTPUT.put_line( 'Finally' ); |
DBMS_OUTPUT.put_line( 'Finally' ); |
||
END; |
END; |
||
/</ |
/</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>startLoop |
<pre>startLoop |
||
Line 2,213: | Line 2,213: | ||
current loop. The syntax for a label is as follows (this example shows a |
current loop. The syntax for a label is as follows (this example shows a |
||
label in a While loop): |
label in a While loop): |
||
<syntaxhighlight lang="powershell"> |
|||
<lang PowerShell> |
|||
:myLabel while (<condition>) { <statement list>} |
:myLabel while (<condition>) { <statement list>} |
||
</syntaxhighlight> |
|||
</lang> |
|||
The label is a colon followed by a name that you assign. The label must be |
The label is a colon followed by a name that you assign. The label must be |
||
the first token in a statement, and it must be followed by the looping |
the first token in a statement, and it must be followed by the looping |
||
Line 2,229: | Line 2,229: | ||
This schematic example has a While statement with a For statement: |
This schematic example has a While statement with a For statement: |
||
<syntaxhighlight lang="powershell"> |
|||
<lang PowerShell> |
|||
:myLabel while (<condition 1>) |
:myLabel while (<condition 1>) |
||
{ |
{ |
||
Line 2,239: | Line 2,239: | ||
} |
} |
||
$a = $c # A statement after the labeled While-loop |
$a = $c # A statement after the labeled While-loop |
||
</syntaxhighlight> |
|||
</lang> |
|||
If condition 2 evaluates to True, the execution of the script skips down |
If condition 2 evaluates to True, the execution of the script skips down |
||
Line 2,247: | Line 2,247: | ||
You can nest many labeled loops, as shown in the following schematic |
You can nest many labeled loops, as shown in the following schematic |
||
example. |
example. |
||
<syntaxhighlight lang="powershell"> |
|||
<lang PowerShell> |
|||
:red while (<condition1>) |
:red while (<condition1>) |
||
{ |
{ |
||
Line 2,263: | Line 2,263: | ||
} |
} |
||
# After "red" loop |
# After "red" loop |
||
</syntaxhighlight> |
|||
</lang> |
|||
If the $b variable evaluates to True, execution of the script resumes |
If the $b variable evaluates to True, execution of the script resumes |
||
after the loop that is labeled "red". If the $c variable evaluates to |
after the loop that is labeled "red". If the $c variable evaluates to |
||
Line 2,276: | Line 2,276: | ||
=={{header|PureBasic}}== |
=={{header|PureBasic}}== |
||
< |
<syntaxhighlight lang="purebasic">OnErrorGoto(?ErrorHandler) |
||
OpenConsole() |
OpenConsole() |
||
Gosub label4 |
Gosub label4 |
||
Line 2,306: | Line 2,306: | ||
ErrorHandler: |
ErrorHandler: |
||
PrintN(ErrorMessage()) : Goto label4</ |
PrintN(ErrorMessage()) : Goto label4</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>eins zwei eins zwei eins zwei - drei -</pre> |
<pre>eins zwei eins zwei eins zwei - drei -</pre> |
||
Line 2,314: | Line 2,314: | ||
The "goto" module was an April Fool's joke, published on 1st April 2004. Yes, it works, but it's a joke nevertheless. Please don't use it in real code! For those who like computer languages with a sense of humour it can be downloded [http://entrian.com/goto/goto-1.0.tar.gz here]. It is well documented and comes with many examples. My favorite: |
The "goto" module was an April Fool's joke, published on 1st April 2004. Yes, it works, but it's a joke nevertheless. Please don't use it in real code! For those who like computer languages with a sense of humour it can be downloded [http://entrian.com/goto/goto-1.0.tar.gz here]. It is well documented and comes with many examples. My favorite: |
||
<syntaxhighlight lang="python"> |
|||
<lang Python> |
|||
# Example 2: Restarting a loop: |
# Example 2: Restarting a loop: |
||
from goto import goto, label |
from goto import goto, label |
||
Line 2,328: | Line 2,328: | ||
goto .start |
goto .start |
||
print output, "\n" |
print output, "\n" |
||
</syntaxhighlight> |
|||
</lang> |
|||
It goes the extra mile and adds a <code>comefrom</code> keyword. This should be used only if you are evil and proud of it. It is reported to have caused maintenance programmers to have so strongly believed themselves insane that it became so. They are now under strong medication in padded cells. Basically whenever the code passes a label it jumps to the comefrom point. For best results I advise writing the comefrom code as far as possible from the label and using no comments near the label. |
It goes the extra mile and adds a <code>comefrom</code> keyword. This should be used only if you are evil and proud of it. It is reported to have caused maintenance programmers to have so strongly believed themselves insane that it became so. They are now under strong medication in padded cells. Basically whenever the code passes a label it jumps to the comefrom point. For best results I advise writing the comefrom code as far as possible from the label and using no comments near the label. |
||
Line 2,336: | Line 2,336: | ||
{{works with|BASIC256}} |
{{works with|BASIC256}} |
||
{{works with|Yabasic}} |
{{works with|Yabasic}} |
||
< |
<syntaxhighlight lang="qbasic"> |
||
PRINT "First line." |
PRINT "First line." |
||
GOSUB sub1 |
GOSUB sub1 |
||
Line 2,358: | Line 2,358: | ||
Finished: |
Finished: |
||
PRINT "... with goto and gosub, thankfully." |
PRINT "... with goto and gosub, thankfully." |
||
END</ |
END</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Igual que la entrada de FutureBasic.</pre> |
<pre>Igual que la entrada de FutureBasic.</pre> |
||
=={{header|QB64}}== |
=={{header|QB64}}== |
||
<syntaxhighlight lang="qb64"> |
|||
<lang QB64> |
|||
' Jumps in QB64 are inherited by Qbasic/ QuickBasic/ GWBasic |
' Jumps in QB64 are inherited by Qbasic/ QuickBasic/ GWBasic |
||
' here a GOTO demo of loops FOR-NEXT and WHILE-WEND |
' here a GOTO demo of loops FOR-NEXT and WHILE-WEND |
||
Line 2,406: | Line 2,406: | ||
Q = Q + 1 |
Q = Q + 1 |
||
GoTo 2 |
GoTo 2 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Quackery}}== |
=={{header|Quackery}}== |
||
Line 2,432: | Line 2,432: | ||
To achieve this, <code>]'[</code> advances the offset on top of the return stack, like <code>]else[</code>, but also puts a copy of the item skipped over on the stack. (i.e. the nest following <code>jump-into</code> in the example) It puts this, with an offset of 0, onto the call stack (with <code>]do[</code>. Then it uses <code>' ]else[ swap of</code> to build a nest of the specified number of instances of <code>]else[</code>, and puts that on the call stack, so that it will be evaluated after exiting <code>jump-to</code>, and increment the offset of the top of the call stack (i.e. the nest following <code>jump-to</code>) that number of times. |
To achieve this, <code>]'[</code> advances the offset on top of the return stack, like <code>]else[</code>, but also puts a copy of the item skipped over on the stack. (i.e. the nest following <code>jump-into</code> in the example) It puts this, with an offset of 0, onto the call stack (with <code>]do[</code>. Then it uses <code>' ]else[ swap of</code> to build a nest of the specified number of instances of <code>]else[</code>, and puts that on the call stack, so that it will be evaluated after exiting <code>jump-to</code>, and increment the offset of the top of the call stack (i.e. the nest following <code>jump-to</code>) that number of times. |
||
< |
<syntaxhighlight lang="quackery"> [ ]'[ ]do[ ' ]else[ swap of ]do[ ] is jump-into ( n --> ) |
||
5 jump-into |
5 jump-into |
||
Line 2,438: | Line 2,438: | ||
( 0 1 2 3 4 offsets of each item ) |
( 0 1 2 3 4 offsets of each item ) |
||
( 5 6 7 8 9 from start of nest ) |
( 5 6 7 8 9 from start of nest ) |
||
2 echo 3 echo again ]</ |
2 echo 3 echo again ]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,448: | Line 2,448: | ||
As a little example: |
As a little example: |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
(define (never-divides-by-zero return) |
(define (never-divides-by-zero return) |
||
(displayln "I'm here") |
(displayln "I'm here") |
||
Line 2,460: | Line 2,460: | ||
; I'm here |
; I'm here |
||
; "Leaving" (because that's what the function returns) |
; "Leaving" (because that's what the function returns) |
||
</syntaxhighlight> |
|||
</lang> |
|||
Here, return is the program continuation being passed to the function, when it is called, the string "Leaving" i the result of the function and the following code is never executed. |
Here, return is the program continuation being passed to the function, when it is called, the string "Leaving" i the result of the function and the following code is never executed. |
||
Line 2,467: | Line 2,467: | ||
Where we generate elements of a list one at a time: |
Where we generate elements of a list one at a time: |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
;; [LISTOF X] -> ( -> X u 'you-fell-off-the-end-off-the-list) |
;; [LISTOF X] -> ( -> X u 'you-fell-off-the-end-off-the-list) |
||
(define (generate-one-element-at-a-time a-list) |
(define (generate-one-element-at-a-time a-list) |
||
Line 2,488: | Line 2,488: | ||
;; time to return the generator |
;; time to return the generator |
||
generator) |
generator) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Relation}}== |
=={{header|Relation}}== |
||
Line 2,497: | Line 2,497: | ||
Retro allows the user to jump to any address. |
Retro allows the user to jump to any address. |
||
< |
<syntaxhighlight lang="retro">:foo #19 &n:inc \ju...... #21 ;</syntaxhighlight> |
||
When executed, the stack will contain 20; control does not return to the '''foo''' function. |
When executed, the stack will contain 20; control does not return to the '''foo''' function. |
||
Line 2,505: | Line 2,505: | ||
===Label-based jumps=== |
===Label-based jumps=== |
||
<lang |
<syntaxhighlight lang="raku" line> outer-loop: loop { |
||
inner-loop: loop { |
inner-loop: loop { |
||
# NYI # goto inner-loop if rand > 0.5; # Hard goto |
# NYI # goto inner-loop if rand > 0.5; # Hard goto |
||
Line 2,517: | Line 2,517: | ||
LEAVE { say "Leaving outer loop block" } |
LEAVE { say "Leaving outer loop block" } |
||
LAST { say "Ending outer loop" } |
LAST { say "Ending outer loop" } |
||
}</ |
}</syntaxhighlight> |
||
Produces random output, but here's a representative run: |
Produces random output, but here's a representative run: |
||
Line 2,533: | Line 2,533: | ||
Continuations in Raku are currently limited to use in generators via the gather/take model: |
Continuations in Raku are currently limited to use in generators via the gather/take model: |
||
<lang |
<syntaxhighlight lang="raku" line> my @list = lazy gather for ^100 -> $i { |
||
if $i.is-prime { |
if $i.is-prime { |
||
say "Taking prime $i"; |
say "Taking prime $i"; |
||
Line 2,540: | Line 2,540: | ||
} |
} |
||
say @list[5];</ |
say @list[5];</syntaxhighlight> |
||
This outputs: |
This outputs: |
||
Line 2,556: | Line 2,556: | ||
Exceptions are fairly typical in Raku: |
Exceptions are fairly typical in Raku: |
||
<lang |
<syntaxhighlight lang="raku" line> die "This is a generic, untyped exception";</syntaxhighlight> |
||
Will walk up the stack until either some `CATCH` block intercepts the specific exception type or we exit the program. |
Will walk up the stack until either some `CATCH` block intercepts the specific exception type or we exit the program. |
||
But if a failure should be recoverable (e.g. execution might reasonably continue along another path) a failure is often the right choice. The fail operator is like "return", but the returned value will only be valid in boolean context or for testing definedness. Any other operation will produce the original exception with the original exception's execution context (e.g. traceback) along with the current context. |
But if a failure should be recoverable (e.g. execution might reasonably continue along another path) a failure is often the right choice. The fail operator is like "return", but the returned value will only be valid in boolean context or for testing definedness. Any other operation will produce the original exception with the original exception's execution context (e.g. traceback) along with the current context. |
||
<lang |
<syntaxhighlight lang="raku" line> sub foo() { fail "oops" } |
||
my $failure = foo; |
my $failure = foo; |
||
say "Called foo"; |
say "Called foo"; |
||
say "foo not true" unless $failure; |
say "foo not true" unless $failure; |
||
say "foo not defined" unless $failure.defined; |
say "foo not defined" unless $failure.defined; |
||
say "incremented foo" if $failure++; # exception</ |
say "incremented foo" if $failure++; # exception</syntaxhighlight> |
||
Produces: |
Produces: |
||
Line 2,579: | Line 2,579: | ||
However, an exception can `.resume` in order to jump back to the failure point (this is why the stack is not unwound until after exception handling). |
However, an exception can `.resume` in order to jump back to the failure point (this is why the stack is not unwound until after exception handling). |
||
<lang |
<syntaxhighlight lang="raku" line> sub foo($i) { |
||
if $i == 0 { |
if $i == 0 { |
||
die "Are you sure you want /0?"; |
die "Are you sure you want /0?"; |
||
Line 2,593: | Line 2,593: | ||
CATCH { |
CATCH { |
||
when ~$_ ~~ m:s/Are you sure/ { .resume; #`(yes, I'm sure) } |
when ~$_ ~~ m:s/Are you sure/ { .resume; #`(yes, I'm sure) } |
||
}</ |
}</syntaxhighlight> |
||
This code raises an exception on a zero input, but then resumes execution, divides be zero and then raises a divide by zero exception which is not caught: |
This code raises an exception on a zero input, but then resumes execution, divides be zero and then raises a divide by zero exception which is not caught: |
||
Line 2,610: | Line 2,610: | ||
<br>as long as the '''END''' or the '''DO''' loop isn't executed. |
<br>as long as the '''END''' or the '''DO''' loop isn't executed. |
||
<br>The following used PC/REXX to illustrate this example. |
<br>The following used PC/REXX to illustrate this example. |
||
< |
<syntaxhighlight lang="rexx">/*REXX pgm demonstrates various jumps (GOTOs). In REXX, it's a SIGNAL. */ |
||
say 'starting...' |
say 'starting...' |
||
signal aJump |
signal aJump |
||
Line 2,628: | Line 2,628: | ||
cJump: say 'and here we are at cJump.' |
cJump: say 'and here we are at cJump.' |
||
exit |
exit |
||
end /*k*/</ |
end /*k*/</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,655: | Line 2,655: | ||
As mentioned above some implementations may have restrictions on that. |
As mentioned above some implementations may have restrictions on that. |
||
This Signal jumps into a Do loop inside a Procedure: |
This Signal jumps into a Do loop inside a Procedure: |
||
< |
<syntaxhighlight lang="rexx">i=13 |
||
signal label |
signal label |
||
say 'This is never executed' |
say 'This is never executed' |
||
Line 2,665: | Line 2,665: | ||
End |
End |
||
Return |
Return |
||
real_start:</ |
real_start:</syntaxhighlight> |
||
Without the 'Signal real_start' which leads us out of the control structure the program would end with a syntax error when encountering the End correponding to the Do. |
Without the 'Signal real_start' which leads us out of the control structure the program would end with a syntax error when encountering the End correponding to the Do. |
||
I recommend to use Signal only for condition handling and 'global' jumps to labels that are not within some structured constructs such as Do...End |
I recommend to use Signal only for condition handling and 'global' jumps to labels that are not within some structured constructs such as Do...End |
||
An example: |
An example: |
||
< |
<syntaxhighlight lang="rexx">/* REXX *************************************************************** |
||
* 12.12.2012 Walter Pachl |
* 12.12.2012 Walter Pachl |
||
**********************************************************************/ |
**********************************************************************/ |
||
Line 2,686: | Line 2,686: | ||
Say 'argument must be a or b or omitted' |
Say 'argument must be a or b or omitted' |
||
Exit |
Exit |
||
eoj: say 'here we could print statistics'</ |
eoj: say 'here we could print statistics'</syntaxhighlight> |
||
This can be useful when the different parts of the program span a few pages. |
This can be useful when the different parts of the program span a few pages. |
||
Also a Signal eoj in order to Exit from any point in the program to some final activities can be useful. |
Also a Signal eoj in order to Exit from any point in the program to some final activities can be useful. |
||
Line 2,698: | Line 2,698: | ||
====Simple==== |
====Simple==== |
||
A simple example of labels and goto: |
A simple example of labels and goto: |
||
< |
<syntaxhighlight lang="robotic"> |
||
. "The label 'touch' is used to let the player touch the robot" |
. "The label 'touch' is used to let the player touch the robot" |
||
. "to execute the following" |
. "to execute the following" |
||
Line 2,712: | Line 2,712: | ||
* "Label B was reached" |
* "Label B was reached" |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
It prints "Label B was reached", skipping "label_a" entirely. |
It prints "Label B was reached", skipping "label_a" entirely. |
||
Line 2,718: | Line 2,718: | ||
====Conditional==== |
====Conditional==== |
||
This will jump to a given label, depending on the condition of "local1": |
This will jump to a given label, depending on the condition of "local1": |
||
< |
<syntaxhighlight lang="robotic"> |
||
set "local1" to 2 |
set "local1" to 2 |
||
end |
end |
||
Line 2,733: | Line 2,733: | ||
* "Label B was reached" |
* "Label B was reached" |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
Since "local1" equals 2, it prints "Label B was reached". |
Since "local1" equals 2, it prints "Label B was reached". |
||
Line 2,740: | Line 2,740: | ||
When you goto a label, it chooses the top-most label name in the code. |
When you goto a label, it chooses the top-most label name in the code. |
||
However, with the use of "zap" and "restore", we can use the same label name multiple times in our code: |
However, with the use of "zap" and "restore", we can use the same label name multiple times in our code: |
||
< |
<syntaxhighlight lang="robotic"> |
||
end |
end |
||
: "touch" |
: "touch" |
||
Line 2,754: | Line 2,754: | ||
restore "label_a" 1 |
restore "label_a" 1 |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
When the first label is reached, it zaps "label_a" once. This allows us to reach the second label below. Conversely, restoring "label_a" allows us to go back to the first label once more. |
When the first label is reached, it zaps "label_a" once. This allows us to reach the second label below. Conversely, restoring "label_a" allows us to go back to the first label once more. |
||
Line 2,761: | Line 2,761: | ||
With subroutines, we can jump to a given label and come back to where we left off after we called the inital "goto" statement. |
With subroutines, we can jump to a given label and come back to where we left off after we called the inital "goto" statement. |
||
To use these, the labels and the string supplied in the "goto" statements must have a number sign (#): |
To use these, the labels and the string supplied in the "goto" statements must have a number sign (#): |
||
< |
<syntaxhighlight lang="robotic"> |
||
. "The 'wait' statements are used to demonstrate what is happening" |
. "The 'wait' statements are used to demonstrate what is happening" |
||
set "local1" to 1 |
set "local1" to 1 |
||
Line 2,791: | Line 2,791: | ||
* "Label D was reached" |
* "Label D was reached" |
||
goto "#top" |
goto "#top" |
||
</syntaxhighlight> |
|||
</lang> |
|||
The following is printed out in order: |
The following is printed out in order: |
||
<lang> |
<syntaxhighlight lang="text"> |
||
Label A was reached |
Label A was reached |
||
Done with Label A |
Done with Label A |
||
Line 2,800: | Line 2,800: | ||
Label D was reached |
Label D was reached |
||
Skipped finishing Label B and C |
Skipped finishing Label B and C |
||
</syntaxhighlight> |
|||
</lang> |
|||
Using "#return", we go back up to the last "goto" statement called. However, using "#top" will ignore all the other subroutines called previously and go straight back to the first "goto" statement that started it all (in this case, goto "#label_b"). |
Using "#return", we go back up to the last "goto" statement called. However, using "#top" will ignore all the other subroutines called previously and go straight back to the first "goto" statement that started it all (in this case, goto "#label_b"). |
||
Line 2,809: | Line 2,809: | ||
The next example abuses a continuation to solve [[FizzBuzz#Ruby]]. It is slower and more confusing than an ordinary loop. |
The next example abuses a continuation to solve [[FizzBuzz#Ruby]]. It is slower and more confusing than an ordinary loop. |
||
{{libheader|continuation}} |
{{libheader|continuation}} |
||
< |
<syntaxhighlight lang="ruby">require 'continuation' unless defined? Continuation |
||
if a = callcc { |c| [c, 1] } |
if a = callcc { |c| [c, 1] } |
||
Line 2,830: | Line 2,830: | ||
puts |
puts |
||
c[c, i + 1] |
c[c, i + 1] |
||
end</ |
end</syntaxhighlight> |
||
This code uses the Continuation object <code>c</code> to jump to the top of the loop. For the first iteration, <code>callcc</code> creates <code>c</code> and returns <code>[c, 1]</code>. For later iterations, <code>callcc</code> returns <code>[c, i + 1]</code>. For the last iteration, <code>callcc</code> returns <code>nil</code> to break the loop. |
This code uses the Continuation object <code>c</code> to jump to the top of the loop. For the first iteration, <code>callcc</code> creates <code>c</code> and returns <code>[c, 1]</code>. For later iterations, <code>callcc</code> returns <code>[c, i + 1]</code>. For the last iteration, <code>callcc</code> returns <code>nil</code> to break the loop. |
||
Line 2,840: | Line 2,840: | ||
In SPL jumps can be non-conditional and conditional. |
In SPL jumps can be non-conditional and conditional. |
||
This is an example of non-conditional jump to label "myLabel": |
This is an example of non-conditional jump to label "myLabel": |
||
< |
<syntaxhighlight lang="spl">myLabel -> |
||
... |
... |
||
:myLabel</ |
:myLabel</syntaxhighlight> |
||
This is an example of conditional jump to label "4", which is done if a=0: |
This is an example of conditional jump to label "4", which is done if a=0: |
||
< |
<syntaxhighlight lang="spl">4 -> a=0 |
||
... |
... |
||
:4</ |
:4</syntaxhighlight> |
||
In SPL it is possible not only jump, but also visit a label. "Visiting" a label means that program execution can be returned back to the place from where label was visited. |
In SPL it is possible not only jump, but also visit a label. "Visiting" a label means that program execution can be returned back to the place from where label was visited. |
||
This is an example of visiting label "label 55": |
This is an example of visiting label "label 55": |
||
< |
<syntaxhighlight lang="spl">label 55 <-> |
||
#.output("1") |
#.output("1") |
||
:label 55 |
:label 55 |
||
#.output("2") |
#.output("2") |
||
<-</ |
<-</syntaxhighlight> |
||
and output is: |
and output is: |
||
{{out}} |
{{out}} |
||
Line 2,864: | Line 2,864: | ||
=={{header|SSEM}}== |
=={{header|SSEM}}== |
||
The SSEM provides two jump instructions: the absolute jump <tt>000 <operand> to CI</tt> and the relative jump <tt>100 Add <operand> to CI</tt>. The operand in both cases is a memory address, whose contents are to be either loaded into the CI (Current Instruction) register or else added to it. Since CI is incremented <i>after</i> an instruction is executed, not before, the value stored at the operand address must be one less than the value we actually want. For example, this code accomplishes a jump to absolute address 20: |
The SSEM provides two jump instructions: the absolute jump <tt>000 <operand> to CI</tt> and the relative jump <tt>100 Add <operand> to CI</tt>. The operand in both cases is a memory address, whose contents are to be either loaded into the CI (Current Instruction) register or else added to it. Since CI is incremented <i>after</i> an instruction is executed, not before, the value stored at the operand address must be one less than the value we actually want. For example, this code accomplishes a jump to absolute address 20: |
||
< |
<syntaxhighlight lang="ssem">10000000000000000000000000000000 0. 1 to CI |
||
11001000000000000000000000000000 1. 19</ |
11001000000000000000000000000000 1. 19</syntaxhighlight> |
||
and this accomplishes a relative jump forward by five words: |
and this accomplishes a relative jump forward by five words: |
||
< |
<syntaxhighlight lang="ssem">10000000000001000000000000000000 0. Add 1 to CI |
||
00100000000000000000000000000000 1. 4</ |
00100000000000000000000000000000 1. 4</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
Line 2,874: | Line 2,874: | ||
=={{header|VBA}}== |
=={{header|VBA}}== |
||
< |
<syntaxhighlight lang="vb">Public Sub jump() |
||
Debug.Print "VBA only allows" |
Debug.Print "VBA only allows" |
||
GoTo 1 |
GoTo 1 |
||
Line 2,892: | Line 2,892: | ||
two: |
two: |
||
Debug.Print "On <n> GoSub let you jump to the n-th label": Return |
Debug.Print "On <n> GoSub let you jump to the n-th label": Return |
||
End Sub</ |
End Sub</syntaxhighlight>{{out}} |
||
<pre>VBA only allows |
<pre>VBA only allows |
||
jumps in procedures with GoTo |
jumps in procedures with GoTo |
||
Line 2,913: | Line 2,913: | ||
If the expression does not evaluate to a line number present in the program, the program continues with the next highest line number or stops if there is no line with a number higher that the expression.<br> |
If the expression does not evaluate to a line number present in the program, the program continues with the next highest line number or stops if there is no line with a number higher that the expression.<br> |
||
The following program demonstrates this - prompiting the user for a label to goto. (In an expression, <code>?</code> indicates a value should be read from the console, assigning to <code>?</code> prints the assigned value)<br> |
The following program demonstrates this - prompiting the user for a label to goto. (In an expression, <code>?</code> indicates a value should be read from the console, assigning to <code>?</code> prints the assigned value)<br> |
||
< |
<syntaxhighlight lang="vtl2">1010 ?="@1010: Where to goto? "; |
||
1020 #=? |
1020 #=? |
||
1030 ?="@1030" |
1030 ?="@1030" |
||
Line 2,920: | Line 2,920: | ||
1060 #=1010 |
1060 #=1010 |
||
2000 ?="@2000" |
2000 ?="@2000" |
||
2010 ?="Exiting..."</ |
2010 ?="Exiting..."</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,949: | Line 2,949: | ||
The Fiber class also has a ''try'' method for catching errors (which won't be described here) and a static ''abort'' method which (unless caught) exits the script altogether if an error occurs. |
The Fiber class also has a ''try'' method for catching errors (which won't be described here) and a static ''abort'' method which (unless caught) exits the script altogether if an error occurs. |
||
< |
<syntaxhighlight lang="ecmascript">var func = Fn.new { |
||
for (i in 1..10) { |
for (i in 1..10) { |
||
if (i == 1) continue // jumps to next iteration when 'i' equals 1 |
if (i == 1) continue // jumps to next iteration when 'i' equals 1 |
||
Line 2,972: | Line 2,972: | ||
System.print("yielding") |
System.print("yielding") |
||
fiber.call() // resumes the fiber |
fiber.call() // resumes the fiber |
||
return // would exit the module (and script) without error but won't be reached</ |
return // would exit the module (and script) without error but won't be reached</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 3,015: | Line 3,015: | ||
{{works with|QBasic}} |
{{works with|QBasic}} |
||
{{works with|BASIC256}} |
{{works with|BASIC256}} |
||
< |
<syntaxhighlight lang="freebasic">print "First line." |
||
gosub sub1 |
gosub sub1 |
||
print "Fifth line." |
print "Fifth line." |
||
Line 3,036: | Line 3,036: | ||
Finished: |
Finished: |
||
print "... with goto and gosub, thankfully." |
print "... with goto and gosub, thankfully." |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Igual que la entrada de FutureBasic.</pre> |
<pre>Igual que la entrada de FutureBasic.</pre> |
||
Line 3,050: | Line 3,050: | ||
<code>JR</code> adds a signed displacement byte to the program counter. This takes one less byte to encode than a <code>JP</code> but cannot jump more than 127 bytes forward or 128 bytes backward. The programmer can either specify a constant value as the operand or a labeled section of code. If a label is used, the assembler will calculate the number of bytes between the <code>JR</code> instruction and that label, and will refuse to assemble the code if the label is too far away. |
<code>JR</code> adds a signed displacement byte to the program counter. This takes one less byte to encode than a <code>JP</code> but cannot jump more than 127 bytes forward or 128 bytes backward. The programmer can either specify a constant value as the operand or a labeled section of code. If a label is used, the assembler will calculate the number of bytes between the <code>JR</code> instruction and that label, and will refuse to assemble the code if the label is too far away. |
||
< |
<syntaxhighlight lang="z80">and &01 ;returns 0 if the accumulator is even and 1 if odd. Also sets the zero flag accordingly. |
||
jr z,SkipOddCode |
jr z,SkipOddCode |
||
;whatever you want to do when the accumulator is odd goes here, but it must be 127 bytes or fewer. |
;whatever you want to do when the accumulator is odd goes here, but it must be 127 bytes or fewer. |
||
SkipOddCode: |
SkipOddCode: |
||
;rest of program</ |
;rest of program</syntaxhighlight> |
||
A similar command called <code>DJNZ</code> is often used for looping. It decrements the B register and jumps if and only if B is nonzero. If B is zero, the <code>DJNZ</code> will do nothing and execution will move past it. Like all other jumping commands discussed so far, <code>DJNZ</code> will not alter the processor flags in any way. The same distance restriction of <code>JR</code> also applies to <code>DJNZ</code>. This is the equivalent of the <code>LOOP</code> instruction in [[x86 Assembly]]. |
A similar command called <code>DJNZ</code> is often used for looping. It decrements the B register and jumps if and only if B is nonzero. If B is zero, the <code>DJNZ</code> will do nothing and execution will move past it. Like all other jumping commands discussed so far, <code>DJNZ</code> will not alter the processor flags in any way. The same distance restriction of <code>JR</code> also applies to <code>DJNZ</code>. This is the equivalent of the <code>LOOP</code> instruction in [[x86 Assembly]]. |
||
< |
<syntaxhighlight lang="z80">ld b,25 |
||
loop: |
loop: |
||
djnz loop ;loop 25 times.</ |
djnz loop ;loop 25 times.</syntaxhighlight> |
||
Line 3,069: | Line 3,069: | ||
<code>JR</code>,<code>JP</code>,<code>CALL</code>, and <code>RET</code> can be made conditional based on which flags are set. Essentially these are like <code>if</code> statements in a high-level language. If the condition specified by the command is not met, the command will have no effect; otherwise it will result in a jump. |
<code>JR</code>,<code>JP</code>,<code>CALL</code>, and <code>RET</code> can be made conditional based on which flags are set. Essentially these are like <code>if</code> statements in a high-level language. If the condition specified by the command is not met, the command will have no effect; otherwise it will result in a jump. |
||
< |
<syntaxhighlight lang="z80">ret po ;return from subroutine if overflow has not occurred or the bit parity has an odd number of 1s. |
||
call c, foo ;call "foo" if and only if the carry is set. |
call c, foo ;call "foo" if and only if the carry is set. |
||
jp m,&ABCD ;jump to address &ABCD if the last operation resulted in a negative value. |
jp m,&ABCD ;jump to address &ABCD if the last operation resulted in a negative value. |
||
jr z,25 ;jump 25 bytes forward if the last operation resulted in a zero. (Some assemblers such as VASM make you type "$+25") |
jr z,25 ;jump 25 bytes forward if the last operation resulted in a zero. (Some assemblers such as VASM make you type "$+25") |
||
;(Unlike the others, JR cannot jump based on the sign flag or parity/overflow flag.)</ |
;(Unlike the others, JR cannot jump based on the sign flag or parity/overflow flag.)</syntaxhighlight> |
||
The Game Boy is more limited than the Z80 in this regard, as it has no sign or overflow flags! It can only use the zero and carry flags for jumps. |
The Game Boy is more limited than the Z80 in this regard, as it has no sign or overflow flags! It can only use the zero and carry flags for jumps. |
||
Line 3,082: | Line 3,082: | ||
<code>JP (HL)</code> can be used to create a "trampoline," which lets you indirectly call a subroutine, provided that subroutine doesn't take <code>HL</code> as an argument. (Otherwise you'll get some unwanted results.) To do this, you need to know the address of the subroutine you wish to call, load it into HL, then <code>CALL</code> any address that contains either <code>JP (HL)</code> or the byte 0xE9. (<code>JP (HL)</code>'s bytecode is 0xE9). Once you do this, execution will effectively "call" the desired routine. For this to work, the desired routine must end in a <code>RET</code>, and balance the stack properly. That way, when it does <code>RET</code>, it will <code>RET</code> to where you were just after the <code>CALL</code>. |
<code>JP (HL)</code> can be used to create a "trampoline," which lets you indirectly call a subroutine, provided that subroutine doesn't take <code>HL</code> as an argument. (Otherwise you'll get some unwanted results.) To do this, you need to know the address of the subroutine you wish to call, load it into HL, then <code>CALL</code> any address that contains either <code>JP (HL)</code> or the byte 0xE9. (<code>JP (HL)</code>'s bytecode is 0xE9). Once you do this, execution will effectively "call" the desired routine. For this to work, the desired routine must end in a <code>RET</code>, and balance the stack properly. That way, when it does <code>RET</code>, it will <code>RET</code> to where you were just after the <code>CALL</code>. |
||
< |
<syntaxhighlight lang="z80"> |
||
ld hl,foo ;rather than directly specifying "foo", you would normally retrieve it by indexing a table. |
ld hl,foo ;rather than directly specifying "foo", you would normally retrieve it by indexing a table. |
||
;This was done only to keep the example as simple as possible. |
;This was done only to keep the example as simple as possible. |
||
Line 3,097: | Line 3,097: | ||
foo: |
foo: |
||
ld a,0 |
ld a,0 |
||
ret</ |
ret</syntaxhighlight> |
||
''NB: If your hardware allows you to define the <code>RST</code> calls to whatever you like, you can speed this up even more by setting one of them to <code>JP (HL)</code>, and invoking that RST as your trampoline rather than the call. The only downside is that you can't conditionally execute an <code>RST</code>, but if you were using a trampoline it likely wasn't going to be conditional anyway.'' |
''NB: If your hardware allows you to define the <code>RST</code> calls to whatever you like, you can speed this up even more by setting one of them to <code>JP (HL)</code>, and invoking that RST as your trampoline rather than the call. The only downside is that you can't conditionally execute an <code>RST</code>, but if you were using a trampoline it likely wasn't going to be conditional anyway.'' |